cpp.mdx 25.3 KB
Newer Older
D
dingbo 已提交
1 2 3 4 5 6
---
sidebar_position: 1
sidebar_label: C/C++
title: C/C++ Connector
---

7
C/C++ developers can use TDengine's client driver and the C/C++ connector, to develop their applications to connect to TDengine clusters for data writing, querying, and other functions. To use it, you need to include the TDengine header file _taos.h_, which lists the function prototypes of the provided APIs; the application also needs to link to the corresponding dynamic libraries on the platform where it is located.
D
dingbo 已提交
8 9 10 11 12

```c
#include <taos.h>
```

13
After TDengine server or client installation, `taos.h` is located at
D
dingbo 已提交
14

15 16
- Linux: `/usr/local/taos/include`
- Windows: `C:\TDengine\include`
D
dingbo 已提交
17

18
The dynamic libraries for the TDengine client driver are located in.
D
dingbo 已提交
19 20 21 22

- Linux: `/usr/local/taos/driver/libtaos.so`
- Windows: `C:\TDengine\taos.dll`

23
## Supported platforms
D
dingbo 已提交
24

25
Please refer to [list of supported platforms](/reference/connector#supported-platforms)
D
dingbo 已提交
26

27
## Supported versions
D
dingbo 已提交
28

29
The version number of the TDengine client driver and the version number of the TDengine server require one-to-one correspondence and recommend using the same version of client driver as what the TDengine server version is. Although a lower version of the client driver is compatible to work with a higher version of the server, if the first three version numbers are the same (i.e., only the fourth version number is different), but it is not recommended. It is strongly discouraged to use a higher version of the client driver to access a lower version of the TDengine server.
D
dingbo 已提交
30

31
## Installation steps
D
dingbo 已提交
32

33
Please refer to the [Installation Steps](/reference/connector#installation-steps) for TDengine client driver installation
D
dingbo 已提交
34

35
## Establishing a connection
D
dingbo 已提交
36

37
The basic process of accessing a TDengine cluster using the client driver is to establish a connection, query and write data, close the connection, and clear the resource.
D
dingbo 已提交
38

39
The following is sample code for establishing a connection, which omits the query and writing sections and shows how to establish a connection, close a connection, and clear a resource.
D
dingbo 已提交
40 41 42 43 44 45 46 47

```c
  TAOS *taos = taos_connect("localhost:6030", "root", "taosdata", NULL, 0);
  if (taos == NULL) {
    printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/);
    exit(1);
  }

48
  /* put your code here for query and writing */
D
dingbo 已提交
49 50 51 52 53

  taos_close(taos);
  taos_cleanup();
```

54
In the above example code, `taos_connect()` establishes a connection to port 6030 on the host where the client application is located, `taos_close()` closes the current connection, and `taos_cleanup()` clears the resources requested and used by the client driver.
D
dingbo 已提交
55 56 57

:::note

58
- If not specified, when the return value of the API is an integer, _0_ means success, the others are error codes representing the reason for failure, and when the return value is a pointer, _NULL_ means failure.
59
- All error codes and their corresponding causes are described in the `taoserror.h` file.
D
dingbo 已提交
60 61 62

:::

63
## Example program
D
dingbo 已提交
64

65
This section shows sample code for standard access methods to TDengine clusters using the client driver.
D
dingbo 已提交
66

67
### Synchronous query example
D
dingbo 已提交
68

69
<details>
70
<summary>Synchronous query</summary>
D
dingbo 已提交
71 72 73 74 75 76 77

```c
{{#include examples/c/demo.c}}
```

</details>

78
### Asynchronous query example
D
dingbo 已提交
79 80

<details>
81
<summary>Asynchronous queries</summary>
D
dingbo 已提交
82 83 84 85 86 87 88

```c
{{#include examples/c/asyncdemo.c}}
```

</details>

89
### Parameter binding example
D
dingbo 已提交
90 91

<details>
92
<summary>Parameter Binding</summary>
D
dingbo 已提交
93 94 95 96 97 98 99

```c
{{#include examples/c/prepare.c}}
```

</details>

100
### Pattern-free writing example
D
dingbo 已提交
101 102

<details>
103
<summary>Mode free write</summary>
D
dingbo 已提交
104 105 106 107 108 109 110

```c
{{#include examples/c/schemaless.c}}
```

</details>

111
### Subscription and consumption example
D
dingbo 已提交
112 113

<details>
114
<summary>Subscribe and consume</summary>
D
dingbo 已提交
115 116 117 118 119 120 121 122

```c
{{#include examples/c/subscribe.c}}
```

</details>

:::info
123 124 125
More example code and downloads are available at [GitHub](https://github.com/taosdata/TDengine/tree/develop/examples/c).
You can find it in the installation directory under the `examples/c` path. This directory has a makefile and can be compiled under Linux by executing `make` directly.
**Hint:** When compiling in an ARM environment, please remove `-msse4.2` from the makefile. This option is only supported on the x64/x86 hardware platforms.
D
dingbo 已提交
126 127 128

:::

129
## API reference
D
dingbo 已提交
130

131
The following describes the basic API, synchronous API, asynchronous API, subscription API, and schemaless write API of TDengine client driver, respectively.
D
dingbo 已提交
132

133
### Basic API
D
dingbo 已提交
134

135
The base API is used to do things like create database connections and provide a runtime environment for the execution of other APIs.
D
dingbo 已提交
136 137 138

- `void taos_init()`

139
  Initializes the runtime environment. If the API is not actively called, the driver will automatically call the API when `taos_connect()` is called, so the program generally does not need to call it manually.
D
dingbo 已提交
140 141 142

- `void taos_cleanup()`

143
  Clean up the runtime environment and should be called before the application exits.
D
dingbo 已提交
144

145
- ` int taos_options(TSDB_OPTION option, const void * arg, ...) `
D
dingbo 已提交
146

147 148 149
  Set client options, currently supports region setting (`TSDB_OPTION_LOCALE`), character set 
(`TSDB_OPTION_CHARSET`), time zone
(`TSDB_OPTION_TIMEZONE`), configuration file path (`TSDB_OPTION_CONFIGDIR`) . The region setting, character set, and time zone default to the current settings of the operating system.
D
dingbo 已提交
150 151 152

- `char *taos_get_client_info()`

153
  Get client version information.
D
dingbo 已提交
154 155 156

- `TAOS *taos_connect(const char *host, const char *user, const char *pass, const char *db, int port)`

157
  Creates a database connection and initializes the connection context. Among the parameters required from the user are:
D
dingbo 已提交
158

159 160 161 162
  - host: FQDN of any node in the TDengine cluster
  - user: user name
  - pass: password
  - db: database name, if the user does not provide, it can also be connected correctly, the user can create a new database through this connection, if the user provides the database name, it means that the database user has already created, the default use of the database
D
dingbo 已提交
163
  - port: the port the taosd program is listening on
D
dingbo 已提交
164

165
  NULL indicates a failure. The application needs to save the returned parameters for subsequent use.
D
dingbo 已提交
166 167

  :::info
168
  The same process can connect to multiple TDengine clusters according to different host/port
D
dingbo 已提交
169 170 171 172 173

  :::

- `char *taos_get_server_info(TAOS *taos)`

174
  Get server-side version information.
D
dingbo 已提交
175

176
- ` int taos_select_db(TAOS *taos, const char *db)`
D
dingbo 已提交
177

178
  Set the current default database to `db`.
D
dingbo 已提交
179 180 181

- `void taos_close(TAOS *taos)`

182
  Closes the connection, where `taos` is the handle returned by `taos_connect()`.
D
dingbo 已提交
183

184
### Synchronous query APIs
D
dingbo 已提交
185

186
The APIs described in this subsection are all synchronous interfaces. After being called by the application, it blocks and waits for a response until it gets a return result or an error message.
D
dingbo 已提交
187 188 189

- `TAOS_RES* taos_query(TAOS *taos, const char *sql)`

190
  Executes an SQL command, either a DQL, DML, or DDL statement. The `taos` parameter is a handle obtained with `taos_connect()`. You can't tell if the result failed by whether the return value is `NULL`, but by parsing the error code in the result set with the `taos_errno()` function.
D
dingbo 已提交
191 192 193

- `int taos_result_precision(TAOS_RES *res)`

194
  Returns the precision of the result set timestamp field, `0` for milliseconds, `1` for microseconds, and `2` for nanoseconds.
D
dingbo 已提交
195 196 197

- `TAOS_ROW taos_fetch_row(TAOS_RES *res)`

198
  Fetch the data in the query result set by row.
D
dingbo 已提交
199

200
- ` int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows)`
D
dingbo 已提交
201

202
  Batch fetches the data in the query result set. The return value is the number of rows of the fetched data.
D
dingbo 已提交
203

204
- `int taos_num_fields(TAOS_RES *res)` and `int taos_field_count(TAOS_RES *res)`
D
dingbo 已提交
205

206
  These two APIs are equivalent and are used to get the number of columns in the query result set.
D
dingbo 已提交
207 208 209

- `int* taos_fetch_lengths(TAOS_RES *res)`

210
  Gets the lengths of each field in the result set. The return value is an array whose length is the number of columns in the result set.
D
dingbo 已提交
211 212 213

- `int taos_affected_rows(TAOS_RES *res)`

214
  Get the number of rows affected by the executed SQL statement.
D
dingbo 已提交
215

216
- ` TAOS_FIELD *taos_fetch_fields(TAOS_RES *res)`
D
dingbo 已提交
217

D
dingbo 已提交
218
  Gets the properties of each column of the query result set (column name, column data type, column length), used in conjunction with `taos_num_fields()` to parse a tuple (one row) of data returned by `taos_fetch_row()`. The structure of `TAOS_FIELD` is as follows.
D
dingbo 已提交
219 220 221

```c
typedef struct taosField {
222 223 224
  char name[65]; // column name
  uint8_t type; // data type
  int16_t bytes; // length, in bytes
D
dingbo 已提交
225 226 227 228 229
} TAOS_FIELD;
```

- `void taos_stop_query(TAOS_RES *res)`

230
  Stops the execution of the current query.
D
dingbo 已提交
231

232
- ` void taos_free_result(TAOS_RES *res)`
D
dingbo 已提交
233

234
  Frees the query result set and the associated resources. Be sure to call this API to free the resources after the query is completed. Otherwise, it may lead to a memory leak in the application. However, note that the application will crash if you call a function like `taos_consume()` to get the query results after freeing the resources.
D
dingbo 已提交
235 236 237

- `char *taos_errstr(TAOS_RES *res)`

238
  Get the reason for the failure of the last API call. The return value is an error message identified by a string.
D
dingbo 已提交
239

240
- 'int taos_errno(TAOS_RES *res)`
D
dingbo 已提交
241

242
  Get the reason for the last API call failure. The return value is the error code.
D
dingbo 已提交
243 244

:::note
245
TDengine version 2.0 and above recommends that each thread of a database application create a separate connection or a connection pool based on threads. It is not recommended to pass the connection (TAOS\*) structure to different threads for shared use in the application. Queries, writes, etc., issued based on TAOS structures are multi-thread safe, but state quantities such as "USE statement" may interfere between threads. In addition, the C connector can dynamically create new database-oriented connections on demand (this procedure is not visible to the user), and it is recommended that `taos_close()` be called only at the final exit of the program to close the connection.
D
dingbo 已提交
246 247 248

:::

249
### Asynchronous query API
D
dingbo 已提交
250

251
TDengine also provides a set of asynchronous API to handle data insertion and query operations with a higher performance. Given the same hardware and software environment, the asynchronous API can run data insertion 2 to 4 times faster than the synchronous API. The asynchronous API is called non-blocking and returns immediately before the system completes a specific database operation. The calling thread can go to work on other tasks, which can improve the performance of the whole application. Asynchronous APIs are particularly advantageous in the case of severe network latency.
D
dingbo 已提交
252

253
The asynchronous APIs require the application to provide a callback function with the following parameters: the first two parameters are consistent, and the third parameter depends on the API. The first parameter, `param`, is provided to the system when the application calls the asynchronous API. It is used for the callback so that the application can retrieve the context of the specific operation, depending on the implementation. The second parameter is the result set of the SQL operation. If it is NULL, such as insert operation, it means that there are no records returned, and if it is not NULL, such as select operation, it means that there are records returned.
D
dingbo 已提交
254

255
The asynchronous API has relatively high user requirements, so users can use it selectively according to specific application scenarios. The following are two important asynchronous APIs.
D
dingbo 已提交
256 257 258

- `void taos_query_a(TAOS *taos, const char *sql, void (*fp)(void *param, TAOS_RES *, int code), void *param);`

259
  Execute SQL command asynchronously.
D
dingbo 已提交
260

261 262 263 264
  - taos: the database connection returned by calling `taos_connect()`
  - sql: the SQL statement to be executed
  - fp: user-defined callback function whose third parameter `code` is used to indicate whether the operation was successful or not, `0` means success, a negative number means failure (call `taos_errstr()` to get the reason for failure). When defining the callback function, the application mainly handles the second parameter `TAOS_RES *`, which is the result set returned by the query
  - param: the application provides a parameter for the callback
D
dingbo 已提交
265 266 267

- `void taos_fetch_rows_a(TAOS_RES *res, void (*fp)(void *param, TAOS_RES *, int numOfRows), void *param);`

268
  Batch get the result set of an asynchronous query, which can only be used with `taos_query_a()`. The parameters are:
D
dingbo 已提交
269

270 271
  - res: the result set returned by the `taos_query_a()` callback
  - fp: callback function. Its parameter `param` is a user-definable parameter structure passed to the callback function; `numOfRows` is the number of rows of the fetched data (not a function of the entire query result set). In the callback function, the application can iterate forward to fetch each row of records in the batch by calling `taos_fetch_row()`. After reading all the rows in a block, the application needs to continue calling `taos_fetch_rows_a()` in the callback function to get the next batch of rows for processing until the number of rows returned, `numOfRows`, is zero (result return complete) or the number of rows is negative (query error).
D
dingbo 已提交
272

273
All TDengine's asynchronous APIs use a non-blocking call pattern. Applications can open multiple tables simultaneously using multiple threads and perform queries or inserts on each open table at the same time. It is important to note that **client applications must ensure that operations on the same table are fully serialized**. i.e., no second insert or query operation can be performed while an insert or query operation on the same table is incomplete (not returned).
D
dingbo 已提交
274

275
### Parameter Binding API
D
dingbo 已提交
276

277
In addition to direct calls to `taos_query()` to perform queries, TDengine also provides a set of `bind` APIs that supports parameter binding, similar in style to MySQL, and currently only supports using a question mark `? ` to represent the parameter to be bound.
D
dingbo 已提交
278

279
Starting with versions 2.1.1.0 and 2.1.2.0, TDengine has significantly improved the bind APIs to support for data writing (INSERT) scenarios. This avoids the resource consumption of SQL syntax parsing when writing data through the parameter binding interface, thus significantly improving write performance in most cases. A typical operation, in this case, is as follows.
D
dingbo 已提交
280

281 282 283 284 285 286 287 288 289
1. call `taos_stmt_init()` to create the parameter binding object.
2. call `taos_stmt_prepare()` to parse the INSERT statement. 3.
3. call `taos_stmt_set_tbname()` to set the table name if it is reserved in the INSERT statement but not the TAGS.
4. call `taos_stmt_set_tbname_tags()` to set the table name and TAGS values if the table name and TAGS are reserved in the INSERT statement (for example, if the INSERT statement takes an automatic table build).
5. call `taos_stmt_bind_param_batch()` to set the value of VALUES in multiple columns, or call `taos_stmt_bind_param()` to set the value of VALUES in a single row.
6. call `taos_stmt_add_batch()` to add the currently bound parameters to the batch.
7. you can repeat steps 3 to 6 to add more rows of data to the batch.
8. call `taos_stmt_execute()` to execute the prepared batch instructions.
9. When execution is complete, call `taos_stmt_close()` to release all resources.
D
dingbo 已提交
290

291
Note: If `taos_stmt_execute()` succeeds, you can reuse the parsed result of `taos_stmt_prepare()` to bind new data in steps 3 to 6 if you don't need to change the SQL command. However, if there is an execution error, it is not recommended to continue working in the current context but release the resources and start again with `taos_stmt_init()` steps.
D
dingbo 已提交
292

293
The specific functions related to the interface are as follows (see also the [prepare.c](https://github.com/taosdata/TDengine/blob/develop/examples/c/prepare.c) file for the way to use the corresponding functions)
D
dingbo 已提交
294 295 296

- `TAOS_STMT* taos_stmt_init(TAOS *taos)`

297
  Creates a TAOS_STMT object for subsequent calls.
D
dingbo 已提交
298

299
- ` int taos_stmt_prepare(TAOS_STMT *stmt, const char *sql, unsigned long length)`
D
dingbo 已提交
300

301
  Parse a SQL command, and bind the parsed result and parameter information to `stmt`. If the parameter length is greater than 0, use this parameter as the length of the SQL command. If it is equal to 0, the length of the SQL command will be determined automatically.
D
dingbo 已提交
302 303 304

- `int taos_stmt_bind_param(TAOS_STMT *stmt, TAOS_BIND *bind)`

305 306
  Not as efficient as `taos_stmt_bind_param_batch()`, but can support non-INSERT type SQL statements.
  To bind parameters, bind points to an array (representing the row of data to be bound), making sure that the number and order of the elements in this array are the same as the parameters in the SQL statement. taos_bind is used similarly to MYSQL_BIND in MySQL, as defined below.
D
dingbo 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

  ```c
  typedef struct TAOS_BIND {
    int            buffer_type;
    void *         buffer;
    uintptr_t      buffer_length;  // not in use
    uintptr_t *    length;
    int *          is_null;
    int            is_unsigned;    // not in use
    int *          error;          // not in use
  } TAOS_BIND;
  ```

- `int taos_stmt_set_tbname(TAOS_STMT* stmt, const char* name)`

322
  (Available in 2.1.1.0 and later versions, only supported for replacing parameter values in INSERT statements)
323
  When the table name in the SQL command uses `? ` placeholder, you can use this function to bind a specific table name.
D
dingbo 已提交
324 325 326

- `int taos_stmt_set_tbname_tags(TAOS_STMT* stmt, const char* name, TAOS_BIND* tags)`

327
  (Available in 2.1.2.0 and later versions, only supported for replacing parameter values in INSERT statements)
328
  When the table name and TAGS in the SQL command both use `? `, you can use this function to bind the specific table name and the specific TAGS value. The most typical usage scenario is an INSERT statement that uses the automatic table building function (the current version does not support specifying specific TAGS columns.) The number of columns in the TAGS parameter needs to be the same as the number of TAGS requested in the SQL command.
D
dingbo 已提交
329 330 331

- `int taos_stmt_bind_param_batch(TAOS_STMT* stmt, TAOS_MULTI_BIND* bind)`

332
  (Available in 2.1.1.0 and later versions, only supported for replacing parameter values in INSERT statements)
333
  To pass the data to be bound in a multi-column manner, it is necessary to ensure that the order of the data columns and the number of columns given here are the same as the VALUES parameter in the SQL statement. The specific definition of TAOS_MULTI_BIND is as follows.
D
dingbo 已提交
334 335 336

  ```c
  typedef struct TAOS_MULTI_BIND {
337 338 339 340 341 342
    int buffer_type;
    void * buffer;
    uintptr_t buffer_length;
    uintptr_t * length;
    char * is_null;
    int num; // the number of columns
D
dingbo 已提交
343 344 345
  } TAOS_MULTI_BIND;
  ```

346
- ` int taos_stmt_add_batch(TAOS_STMT *stmt)`
D
dingbo 已提交
347

348
  Adds the currently bound parameter to the batch. After calling this function, you can call `taos_stmt_bind_param()` or `taos_stmt_bind_param_batch()` again to bind a new parameter. Note that this function only supports INSERT/IMPORT statements. Other SQL command such as SELECT will return an error.
D
dingbo 已提交
349 350 351

- `int taos_stmt_execute(TAOS_STMT *stmt)`

352
  Execute the prepared statement. Currently, a statement can only be executed once.
D
dingbo 已提交
353

354
- ` TAOS_RES* taos_stmt_use_result(TAOS_STMT *stmt)`
D
dingbo 已提交
355

356
  Gets the result set of a statement. Use the result set in the same way as in the non-parametric call. When finished, `taos_free_result()` should be called on this result set to free resources.
D
dingbo 已提交
357 358 359

- `int taos_stmt_close(TAOS_STMT *stmt)`

360
  Finish execution and release all resources.
D
dingbo 已提交
361

362
- ` char * taos_stmt_errstr(TAOS_STMT *stmt)`
D
dingbo 已提交
363

364
  (Available in 2.1.3.0 and later versions)
365
  Used to get error information if other STMT APIs return errors (return error codes or null pointers).
D
dingbo 已提交
366

367
### Schemaless Writing API
D
dingbo 已提交
368

369
In addition to writing data using the SQL method or the parameter binding API, writing can also be done using schemaless writing, which eliminates the need to create a super table/data sub-table structure in advance and writes the data directly. The TDengine system automatically creates and maintains the required table structure based on the written data content. The use of schemaless writing is described in the chapter [Schemaless Writing](/reference/schemaless/), and the C/C++ API used with it is described here.
D
dingbo 已提交
370 371 372

- `TAOS_RES* taos_schemaless_insert(TAOS* taos, const char* lines[], int numLines, int protocol, int precision)`

373 374
  **Function description**
  This interface writes the text data of the line protocol to TDengine.
D
dingbo 已提交
375

376
  **Parameter description**
377 378 379 380 381
  - taos: database connection, established by the `taos_connect()` function.
  - lines: text data. A pattern-free text string that meets the parsing format requirements.
  - numLines: the number of lines of text data, cannot be 0.
  - protocol: the protocol type of the lines, used to identify the text data format.
  - precision: precision string for the timestamp in the text data.
D
dingbo 已提交
382

383 384 385 386
  **return value**
  TAOS_RES structure, application can get error message by using `taos_errstr()` and also error code by using `taos_errno()`.
  In some cases, the returned TAOS_RES is `NULL`, and it is still possible to call `taos_errno()` to safely get the error code information.
  The returned TAOS_RES needs to be freed by the caller. Otherwise, a memory leak will occur.
D
dingbo 已提交
387

388 389
  **Description**
  The protocol type is enumerated and contains the following three formats.
D
dingbo 已提交
390

391 392 393
  - TSDB_SML_LINE_PROTOCOL: InfluxDB line protocol (Line Protocol)
  - TSDB_SML_TELNET_PROTOCOL: OpenTSDB Telnet Text Line Protocol
  - TSDB_SML_JSON_PROTOCOL: OpenTSDB Json protocol format
D
dingbo 已提交
394

395
  The timestamp resolution definitions are in the taos.h file, as follows
D
dingbo 已提交
396 397 398 399 400 401 402 403 404

  - TSDB_SML_TIMESTAMP_NOT_CONFIGURED = 0,
  - TSDB_SML_TIMESTAMP_HOURS,
  - TSDB_SML_TIMESTAMP_MINUTES,
  - TSDB_SML_TIMESTAMP_SECONDS,
  - TSDB_SML_TIMESTAMP_MILLI_SECONDS,
  - TSDB_SML_TIMESTAMP_MICRO_SECONDS,
  - TSDB_SML_TIMESTAMP_NANO_SECONDS

405 406
  Note that the timestamp resolution parameter only takes effect when the protocol type is `SML_LINE_PROTOCOL`.
  For OpenTSDB's text protocol, timestamp resolution follows its official resolution rules - time precision is confirmed by the number of characters contained in the timestamp.
D
dingbo 已提交
407

408 409
  **Supported Versions**
  This feature interface is supported from version 2.3.0.0.
D
dingbo 已提交
410

411
### Subscription and Consumption API
D
dingbo 已提交
412

413
The Subscription API currently supports subscribing to one or more tables and continuously fetching the latest data written to them by polling periodically.
D
dingbo 已提交
414 415 416

- `TAOS_SUB *taos_subscribe(TAOS* taos, int restart, const char* topic, const char *sql, TAOS_SUBSCRIBE_CALLBACK fp, void *param, int interval)`

417
  This function is responsible for starting the subscription service, returning the subscription object on success and `NULL` on failure, with the following parameters.
D
dingbo 已提交
418

419 420 421
  - taos: the database connection that has been established
  - restart: if the subscription already exists, whether to restart or continue the previous subscription
  - topic: the topic of the subscription (i.e., the name). This parameter is the unique identifier of the subscription
422
  - sql: the query statement of the subscription, this statement can only be _select_ statement, only the original data should be queried, only the data can be queried in time order
423 424 425
  - fp: the callback function when the query result is received (the function prototype will be introduced later), only used when called asynchronously. This parameter should be passed `NULL` when called synchronously
  - param: additional parameter when calling the callback function, the system API will pass it to the callback function as it is, without any processing
  - interval: polling period in milliseconds. The callback function will be called periodically according to this parameter when called asynchronously. not recommended to set this parameter too small To avoid impact on system performance when called synchronously. If the interval between two calls to `taos_consume()` is less than this period, the API will block until the interval exceeds this period.
D
dingbo 已提交
426

427
- ` typedef void (*TAOS_SUBSCRIBE_CALLBACK)(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code)`
D
dingbo 已提交
428

429
  The prototype of the callback function in asynchronous mode with the following parameters
D
dingbo 已提交
430

431 432 433 434
  - tsub: subscription object
  - res: query result set, note that there may be no records in the result set
  - param: additional parameters provided by the client program when calling `taos_subscribe()`
  - code: error code
D
dingbo 已提交
435 436

  :::note
437
  The callback function should not take too long to process, especially if the returned result set has a lot of data. Otherwise, it may lead to an abnormal state, such as client blocking. If you must perform complex calculations, we recommend handling them in a separate thread.
D
dingbo 已提交
438 439 440 441 442

  :::

- `TAOS_RES *taos_consume(TAOS_SUB *tsub)`

443
  In synchronous mode, this function is used to fetch the results of a subscription. The user application places it in a loop. If the interval between two calls to `taos_consume()` is less than the polling period of the subscription, the API will block until the interval exceeds this period. If a new record arrives in the database, the API returns that latest record. Otherwise, it returns an empty result set with no records. If the return value is `NULL`, there is a system error. This API should not be called by user programs in asynchronous mode.
D
dingbo 已提交
444 445

  :::note
446
  After calling `taos_consume()`, the user application should make sure to call `taos_fetch_row()` or `taos_fetch_block()` to process the subscription results as soon as possible. Otherwise, the server-side will keep caching the query result data waiting to be read by the client, which in extreme cases will cause the server side to run out of memory and affect the stability of the service.
D
dingbo 已提交
447 448 449 450 451

  :::

- `void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress)`

452
  Unsubscribe. If the parameter `keepProgress` is not 0, the API will keep the progress information of the subscription, and subsequent calls to `taos_subscribe()` will continue based on this progress; otherwise, the progress information will be deleted, and subsequent readings will have to be restarted.