diff --git a/docs-cn/04-develop/04-query-data/_c_async.mdx b/docs-cn/04-develop/04-query-data/_c_async.mdx
index ffdd53306b1198fbd0332d0f403d20f6908d8e1b..09f3d3b3ff6d6644f837642ef41db459ba7c5753 100644
--- a/docs-cn/04-develop/04-query-data/_c_async.mdx
+++ b/docs-cn/04-develop/04-query-data/_c_async.mdx
@@ -1,3 +1,3 @@
```c
-{{#include docs-examples/c/async_query_example.c}}
+{{#include docs-examples/c/async_query_example.c:demo}}
```
\ No newline at end of file
diff --git a/docs-cn/04-develop/04-query-data/index.mdx b/docs-cn/04-develop/04-query-data/index.mdx
index 2185d6a3d81ca8177dc8ff5451e45a8927d5646e..829280fba5b1e5a956b79699df39f9bb2c1cb177 100644
--- a/docs-cn/04-develop/04-query-data/index.mdx
+++ b/docs-cn/04-develop/04-query-data/index.mdx
@@ -172,7 +172,7 @@ Query OK, 5 row(s) in set (0.001521s)
- {/*
+
- */}
+
diff --git a/docs-cn/14-reference/03-connector/python.mdx b/docs-cn/14-reference/03-connector/python.mdx
index 78cb241e95ff6d88560e5f01bf5bd953b1a793a1..abe569ed2683b84eb7cf586a15efec25237ddaf3 100644
--- a/docs-cn/14-reference/03-connector/python.mdx
+++ b/docs-cn/14-reference/03-connector/python.mdx
@@ -340,7 +340,7 @@ TaosCursor 类使用原生连接进行写入、查询操作。在客户端多线
| 连接器版本 | 重要更新 | 发布日期 |
| ---------- | --------------------------------------------------------------------------------- | ---------- |
-| 2.3.0 | 1. support TDengine REST API
2. remove support for Python version below 3.6 | 2022-04-27 |
+| 2.3.1 | 1. support TDengine REST API
2. remove support for Python version below 3.6 | 2022-04-28 |
| 2.2.5 | support timezone option when connect | 2022-04-13 |
| 2.2.2 | support sqlalchemy dialect plugin | 2022-03-28 |
diff --git a/docs-examples/c/async_query_example.c b/docs-examples/c/async_query_example.c
index ec7bd61293a36f7be44c1255ddff9aa6da1795e2..77002891bb4c03f7c7e32b329678e8a124f12a99 100644
--- a/docs-examples/c/async_query_example.c
+++ b/docs-examples/c/async_query_example.c
@@ -1,4 +1,195 @@
-// compiple with:
+// compile with:
// gcc -o async_query_example async_query_example.c -ltaos
-// writing...
\ No newline at end of file
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef int16_t VarDataLenT;
+
+#define TSDB_NCHAR_SIZE sizeof(int32_t)
+#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
+
+#define GET_FLOAT_VAL(x) (*(float *)(x))
+#define GET_DOUBLE_VAL(x) (*(double *)(x))
+
+#define varDataLen(v) ((VarDataLenT *)(v))[0]
+
+int printRow(char *str, TAOS_ROW row, TAOS_FIELD *fields, int numFields) {
+ int len = 0;
+ char split = ' ';
+
+ for (int i = 0; i < numFields; ++i) {
+ if (i > 0) {
+ str[len++] = split;
+ }
+
+ if (row[i] == NULL) {
+ len += sprintf(str + len, "%s", "NULL");
+ continue;
+ }
+
+ switch (fields[i].type) {
+ case TSDB_DATA_TYPE_TINYINT:
+ len += sprintf(str + len, "%d", *((int8_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_UTINYINT:
+ len += sprintf(str + len, "%u", *((uint8_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_SMALLINT:
+ len += sprintf(str + len, "%d", *((int16_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_USMALLINT:
+ len += sprintf(str + len, "%u", *((uint16_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_INT:
+ len += sprintf(str + len, "%d", *((int32_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_UINT:
+ len += sprintf(str + len, "%u", *((uint32_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_BIGINT:
+ len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_UBIGINT:
+ len += sprintf(str + len, "%" PRIu64, *((uint64_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_FLOAT: {
+ float fv = 0;
+ fv = GET_FLOAT_VAL(row[i]);
+ len += sprintf(str + len, "%f", fv);
+ } break;
+
+ case TSDB_DATA_TYPE_DOUBLE: {
+ double dv = 0;
+ dv = GET_DOUBLE_VAL(row[i]);
+ len += sprintf(str + len, "%lf", dv);
+ } break;
+
+ case TSDB_DATA_TYPE_BINARY:
+ case TSDB_DATA_TYPE_NCHAR: {
+ int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE);
+ memcpy(str + len, row[i], charLen);
+ len += charLen;
+ } break;
+
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ len += sprintf(str + len, "%" PRId64, *((int64_t *)row[i]));
+ break;
+
+ case TSDB_DATA_TYPE_BOOL:
+ len += sprintf(str + len, "%d", *((int8_t *)row[i]));
+ default:
+ break;
+ }
+ }
+
+ return len;
+}
+
+void printHeader(TAOS_RES *res) {
+ int numFields = taos_num_fields(res);
+ TAOS_FIELD *fields = taos_fetch_fields(res);
+ char header[256] = {0};
+ int len = 0;
+ for (int i = 0; i < numFields; ++i) {
+ len += sprintf(header + len, "%s ", fields[i].name);
+ }
+ puts(header);
+}
+
+// ANCHOR: demo
+
+/**
+ * @brief call back function of taos_fetch_row_a
+ *
+ * @param param : the third parameter you passed to taos_fetch_row_a
+ * @param res : pointer of TAOS_RES
+ * @param numOfRow : number of rows fetched in this batch. will be 0 if there is no more data.
+ * @return void*
+ */
+void *fetch_row_callback(void *param, TAOS_RES *res, int numOfRow) {
+ printf("numOfRow = %d \n", numOfRow);
+ int numFields = taos_num_fields(res);
+ TAOS_FIELD *fields = taos_fetch_fields(res);
+ TAOS *_taos = (TAOS *)param;
+ if (numOfRow > 0) {
+ for (int i = 0; i < numOfRow; ++i) {
+ TAOS_ROW row = taos_fetch_row(res);
+ char temp[256] = {0};
+ printRow(temp, row, fields, numFields);
+ puts(temp);
+ }
+ taos_fetch_rows_a(res, fetch_row_callback, _taos);
+ } else {
+ printf("no more data, close the connection.\n");
+ taos_free_result(res);
+ taos_close(_taos);
+ taos_cleanup();
+ }
+}
+
+/**
+ * @brief callback function of taos_query_a
+ *
+ * @param param: the fourth parameter you passed to taos_query_a
+ * @param res : the result set
+ * @param code : status code
+ * @return void*
+ */
+void *select_callback(void *param, TAOS_RES *res, int code) {
+ printf("query callback ...\n");
+ TAOS *_taos = (TAOS *)param;
+ if (code == 0 && res) {
+ printHeader(res);
+ taos_fetch_rows_a(res, fetch_row_callback, _taos);
+ } else {
+ printf("failed to exeuce taos_query. error: %s\n", taos_errstr(res));
+ taos_free_result(res);
+ taos_close(_taos);
+ taos_cleanup();
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main() {
+ TAOS *taos = taos_connect("localhost", "root", "taosdata", "power", 6030);
+ if (taos == NULL) {
+ puts("failed to connect to server");
+ exit(EXIT_FAILURE);
+ }
+ // param one is the connection returned by taos_connect.
+ // param two is the SQL to execute.
+ // param three is the callback function.
+ // param four can be any pointer. It will be passed to your callback function as the first parameter. we use taos
+ // here, because we want to close it after getting data.
+ taos_query_a(taos, "SELECT * FROM meters", select_callback, taos);
+ sleep(1);
+}
+
+// output:
+// query callback ...
+// ts current voltage phase location groupid
+// numOfRow = 8
+// 1538548685000 10.300000 219 0.310000 beijing.chaoyang 2
+// 1538548695000 12.600000 218 0.330000 beijing.chaoyang 2
+// 1538548696800 12.300000 221 0.310000 beijing.chaoyang 2
+// 1538548696650 10.300000 218 0.250000 beijing.chaoyang 3
+// 1538548685500 11.800000 221 0.280000 beijing.haidian 2
+// 1538548696600 13.400000 223 0.290000 beijing.haidian 2
+// 1538548685000 10.800000 223 0.290000 beijing.haidian 3
+// 1538548686500 11.500000 221 0.350000 beijing.haidian 3
+// numOfRow = 0
+// no more data, close the connection.
+// ANCHOR_END: demo
\ No newline at end of file
diff --git a/tests/docs-examples-test/test_c.sh b/tests/docs-examples-test/test_c.sh
index 520f795f09f66298e6590edac84e7b4ccfab96a5..2d47eff585b26659cb90a1669317efe074f1adde 100755
--- a/tests/docs-examples-test/test_c.sh
+++ b/tests/docs-examples-test/test_c.sh
@@ -16,6 +16,9 @@ taos -s "drop database if exists power"
gcc -o insert_example insert_example.c -ltaos
./insert_example
+gcc -o async_query_example async_query_example.c -ltaos
+./async_query_example
+
# 3
taos -s "drop database if exists power"
gcc -o stmt_example stmt_example.c -ltaos