From 118b2b98779b2f248db8a4a2586a5ecb3c6e6702 Mon Sep 17 00:00:00 2001 From: t_max <1172915550@qq.com> Date: Mon, 30 Dec 2024 09:34:50 +0800 Subject: [PATCH 1/3] docs: go connector support native stmt2 binding --- docs/en/07-develop/05-stmt.md | 10 +++ docs/en/14-reference/05-connector/20-go.md | 37 +++++++++ docs/examples/go/stmt2/native/main.go | 84 +++++++++++++++++++++ docs/zh/07-develop/05-stmt.md | 11 +++ docs/zh/14-reference/05-connector/20-go.mdx | 31 ++++++++ 5 files changed, 173 insertions(+) create mode 100644 docs/examples/go/stmt2/native/main.go diff --git a/docs/en/07-develop/05-stmt.md b/docs/en/07-develop/05-stmt.md index 4503bb8bd3..614d867c9e 100644 --- a/docs/en/07-develop/05-stmt.md +++ b/docs/en/07-develop/05-stmt.md @@ -96,9 +96,19 @@ This is a [more detailed parameter binding example](https://github.com/taosdata/ + +The example code for binding parameters with stmt2 (Go connector v3.6.0 and above, TDengine v3.3.5.0 and above) is as follows: + +```go +{{#include docs/examples/go/stmt2/native/main.go}} +``` + +The example code for binding parameters with stmt is as follows: + ```go {{#include docs/examples/go/stmt/native/main.go}} ``` + diff --git a/docs/en/14-reference/05-connector/20-go.md b/docs/en/14-reference/05-connector/20-go.md index dd32df2c5b..aecad76a2e 100644 --- a/docs/en/14-reference/05-connector/20-go.md +++ b/docs/en/14-reference/05-connector/20-go.md @@ -493,6 +493,43 @@ The `af` package provides more interfaces using native connections for parameter * **Interface Description**: Closes the statement. * **Return Value**: Error information. +From version 3.6.0, the `stmt2` interface for binding parameters is provided. + +* `func (conn *Connector) Stmt2(reqID int64, singleTableBindOnce bool) *Stmt2` + * **Interface Description**: Returns a Stmt2 object bound to this connection. + * **Parameter Description**: + * `reqID`: Request ID. + * `singleTableBindOnce`: Indicates whether a single child table is bound only once during a single execution. + * **Return Value**: Stmt2 object. + +* `func (s *Stmt2) Prepare(sql string) error` + * **Interface Description**: Prepares an SQL. + * **Parameter Description**: + * `sql`: The statement for parameter binding. + * **Return Value**: Error information. + +* `func (s *Stmt2) Bind(params []*stmt.TaosStmt2BindData) error` + * **Interface Description**: Binds data to the prepared statement. + * **Parameter Description**: + * `params`: The data to bind. + * **Return Value**: Error information. + +* `func (s *Stmt2) Execute() error` + * **Interface Description**: Executes the batch. + * **Return Value**: Error information. + +* `func (s *Stmt2) GetAffectedRows() int` + * **Interface Description**: Gets the number of affected rows (only valid for insert statements). + * **Return Value**: Number of affected rows. + +* `func (s *Stmt2) UseResult() (driver.Rows, error)` + * **Interface Description**: Retrieves the result set (only valid for query statements). + * **Return Value**: Result set Rows object, error information. + +* `func (s *Stmt2) Close() error` + * **Interface Description**: Closes the statement. + * **Return Value**: Error information. + The `ws/stmt` package provides interfaces for parameter binding via WebSocket * `func (c *Connector) Init() (*Stmt, error)` diff --git a/docs/examples/go/stmt2/native/main.go b/docs/examples/go/stmt2/native/main.go new file mode 100644 index 0000000000..fc3ab763c2 --- /dev/null +++ b/docs/examples/go/stmt2/native/main.go @@ -0,0 +1,84 @@ +package main + +import ( + "database/sql/driver" + "fmt" + "log" + "math/rand" + "time" + + "github.com/taosdata/driver-go/v3/af" + "github.com/taosdata/driver-go/v3/common" + "github.com/taosdata/driver-go/v3/common/stmt" +) + +func main() { + host := "127.0.0.1" + numOfSubTable := 10 + numOfRow := 10 + db, err := af.Open(host, "root", "taosdata", "", 0) + if err != nil { + log.Fatalln("Failed to connect to " + host + "; ErrMessage: " + err.Error()) + } + defer db.Close() + // prepare database and table + _, err = db.Exec("CREATE DATABASE IF NOT EXISTS power") + if err != nil { + log.Fatalln("Failed to create database power, ErrMessage: " + err.Error()) + } + _, err = db.Exec("USE power") + if err != nil { + log.Fatalln("Failed to use database power, ErrMessage: " + err.Error()) + } + _, err = db.Exec("CREATE STABLE IF NOT EXISTS meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (groupId INT, location BINARY(24))") + if err != nil { + log.Fatalln("Failed to create stable meters, ErrMessage: " + err.Error()) + } + // prepare statement + sql := "INSERT INTO ? USING meters TAGS(?,?) VALUES (?,?,?,?)" + reqID := common.GetReqID() + stmt2 := db.Stmt2(reqID, false) + err = stmt2.Prepare(sql) + if err != nil { + log.Fatalln("Failed to prepare sql, sql: " + sql + ", ErrMessage: " + err.Error()) + } + for i := 1; i <= numOfSubTable; i++ { + // generate column data + current := time.Now() + columns := make([][]driver.Value, 4) + for j := 0; j < numOfRow; j++ { + columns[0] = append(columns[0], current.Add(time.Millisecond*time.Duration(j))) + columns[1] = append(columns[1], rand.Float32()*30) + columns[2] = append(columns[2], rand.Int31n(300)) + columns[3] = append(columns[3], rand.Float32()) + } + // generate bind data + tableName := fmt.Sprintf("d_bind_%d", i) + tags := []driver.Value{int32(i), []byte(fmt.Sprintf("location_%d", i))} + bindData := []*stmt.TaosStmt2BindData{ + { + TableName: tableName, + Tags: tags, + Cols: columns, + }, + } + // bind params + err = stmt2.Bind(bindData) + if err != nil { + log.Fatalln("Failed to bind params, ErrMessage: " + err.Error()) + } + // execute batch + err = stmt2.Execute() + if err != nil { + log.Fatalln("Failed to exec, ErrMessage: " + err.Error()) + } + // get affected rows + affected := stmt2.GetAffectedRows() + // you can check exeResult here + fmt.Printf("Successfully inserted %d rows to %s.\n", affected, tableName) + } + err = stmt2.Close() + if err != nil { + log.Fatal("failed to close statement, err:", err) + } +} diff --git a/docs/zh/07-develop/05-stmt.md b/docs/zh/07-develop/05-stmt.md index 74b44ba8e6..2cc5413a03 100644 --- a/docs/zh/07-develop/05-stmt.md +++ b/docs/zh/07-develop/05-stmt.md @@ -91,9 +91,20 @@ import TabItem from "@theme/TabItem"; ``` + +stmt2 绑定参数的示例代码如下(go 连接器 v3.6.0 及以上,TDengine v3.3.5.0 及以上): + +```go +{{#include docs/examples/go/stmt2/native/main.go}} +``` + +stmt 绑定参数的示例代码如下: + ```go {{#include docs/examples/go/stmt/native/main.go}} ``` + + diff --git a/docs/zh/14-reference/05-connector/20-go.mdx b/docs/zh/14-reference/05-connector/20-go.mdx index 85c65a5fb8..a4d7b9be71 100644 --- a/docs/zh/14-reference/05-connector/20-go.mdx +++ b/docs/zh/14-reference/05-connector/20-go.mdx @@ -494,6 +494,37 @@ Prepare 允许使用预编译的 SQL 语句,可以提高性能并提供参数 - **接口说明**:关闭语句。 - **返回值**:错误信息。 +从 3.6.0 版本开始,提供 stmt2 绑定参数的接口 + +- `func (conn *Connector) Stmt2(reqID int64, singleTableBindOnce bool) *Stmt2` + - **接口说明**:从连接创建 stmt2。 + - **参数说明**: + - `reqID`:请求 ID。 + - `singleTableBindOnce`:单个子表在单次执行中只有一次数据绑定。 + - **返回值**:stmt2 对象。 +- `func (s *Stmt2) Prepare(sql string) error` + - **接口说明**:绑定 sql 语句。 + - **参数说明**: + - `sql`:要绑定的 sql 语句。 + - **返回值**:错误信息。 +- `func (s *Stmt2) Bind(params []*stmt.TaosStmt2BindData) error` + - **接口说明**:绑定数据。 + - **参数说明**: + - params要绑定的数据。 + - **返回值**:错误信息。 +- `func (s *Stmt2) Execute() error` + - **接口说明**:执行语句。 + - **返回值**:错误信息。 +- `func (s *Stmt2) GetAffectedRows() int` + - **接口说明**:获取受影响行数(只在插入语句有效)。 + - **返回值**:受影响行数。 +- `func (s *Stmt2) UseResult() (driver.Rows, error)` + - **接口说明**:获取结果集(只在查询语句有效)。 + - **返回值**:结果集 Rows 对象,错误信息。 +- `func (s *Stmt2) Close() error` + - **接口说明**:关闭stmt2。 + - **返回值**:错误信息。 + `ws/stmt` 包提供了通过 WebSocket 进行参数绑定的接口 - `func (c *Connector) Init() (*Stmt, error)` From af434a28318d69e8c16dc46e485fd840877e39b4 Mon Sep 17 00:00:00 2001 From: t_max <1172915550@qq.com> Date: Mon, 30 Dec 2024 10:49:41 +0800 Subject: [PATCH 2/3] docs: go connector v3.6.0 --- docs/en/14-reference/05-connector/20-go.md | 39 +++++++++++---------- docs/zh/14-reference/05-connector/20-go.mdx | 39 +++++++++++---------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/docs/en/14-reference/05-connector/20-go.md b/docs/en/14-reference/05-connector/20-go.md index aecad76a2e..bf0e6dd979 100644 --- a/docs/en/14-reference/05-connector/20-go.md +++ b/docs/en/14-reference/05-connector/20-go.md @@ -21,24 +21,25 @@ Supports Go 1.14 and above. ## Version History -| driver-go Version | Major Changes | TDengine Version | -|------------------|------------------------------------------------------------------|-------------------| -| v3.5.8 | Fixed null pointer exception. | - | -| v3.5.7 | taosWS and taosRestful support passing request id. | - | -| v3.5.6 | Improved websocket query and insert performance. | 3.3.2.0 and higher | -| v3.5.5 | Restful supports skipping SSL certificate check. | - | -| v3.5.4 | Compatible with TDengine 3.3.0.0 tmq raw data. | - | -| v3.5.3 | Refactored taosWS. | - | -| v3.5.2 | Websocket compression and optimized tmq subscription performance. | 3.2.3.0 and higher | -| v3.5.1 | Native stmt query and geometry type support. | 3.2.1.0 and higher | -| v3.5.0 | Support tmq get assignment and seek offset. | 3.0.5.0 and higher | -| v3.3.1 | Schemaless protocol insert based on websocket. | 3.0.4.1 and higher | -| v3.1.0 | Provided Kafka-like subscription API. | - | -| v3.0.4 | Added request id related interfaces. | 3.0.2.2 and higher | -| v3.0.3 | Websocket-based statement insert. | - | -| v3.0.2 | Websocket-based data query and insert. | 3.0.1.5 and higher | -| v3.0.1 | Websocket-based message subscription. | - | -| v3.0.0 | Adapted to TDengine 3.0 query and insert. | 3.0.0.0 and higher | +| driver-go Version | Major Changes | TDengine Version | +|-------------------|-------------------------------------------------------------------------------------------------|--------------------| +| v3.6.0 | stmt2 native interface, DSN supports passwords containing special characters (url.QueryEscape). | 3.3.5.0 and higher | +| v3.5.8 | Fixed null pointer exception. | - | +| v3.5.7 | taosWS and taosRestful support passing request id. | - | +| v3.5.6 | Improved websocket query and insert performance. | 3.3.2.0 and higher | +| v3.5.5 | Restful supports skipping SSL certificate check. | - | +| v3.5.4 | Compatible with TDengine 3.3.0.0 tmq raw data. | - | +| v3.5.3 | Refactored taosWS. | - | +| v3.5.2 | Websocket compression and optimized tmq subscription performance. | 3.2.3.0 and higher | +| v3.5.1 | Native stmt query and geometry type support. | 3.2.1.0 and higher | +| v3.5.0 | Support tmq get assignment and seek offset. | 3.0.5.0 and higher | +| v3.3.1 | Schemaless protocol insert based on websocket. | 3.0.4.1 and higher | +| v3.1.0 | Provided Kafka-like subscription API. | - | +| v3.0.4 | Added request id related interfaces. | 3.0.2.2 and higher | +| v3.0.3 | Websocket-based statement insert. | - | +| v3.0.2 | Websocket-based data query and insert. | 3.0.1.5 and higher | +| v3.0.1 | Websocket-based message subscription. | - | +| v3.0.0 | Adapted to TDengine 3.0 query and insert. | 3.0.0.0 and higher | ## Exceptions and Error Codes @@ -136,6 +137,8 @@ Full form of DSN: username:password@protocol(address)/dbname?param=value ``` +When the password contains special characters, it needs to be escaped using url.QueryEscape. + ##### Native Connection Import the driver: diff --git a/docs/zh/14-reference/05-connector/20-go.mdx b/docs/zh/14-reference/05-connector/20-go.mdx index a4d7b9be71..210b0e438d 100644 --- a/docs/zh/14-reference/05-connector/20-go.mdx +++ b/docs/zh/14-reference/05-connector/20-go.mdx @@ -23,24 +23,25 @@ import RequestId from "./_request_id.mdx"; ## 版本历史 -| driver-go 版本 | 主要变化 | TDengine 版本 | -|-------------|-------------------------------------|---------------| -| v3.5.8 | 修复空指针异常 | - | -| v3.5.7 | taosWS 和 taosRestful 支持传入 request id | - | -| v3.5.6 | 提升 websocket 查询和写入性能 | 3.3.2.0 及更高版本 | -| v3.5.5 | restful 支持跳过 ssl 证书检查 | - | -| v3.5.4 | 兼容 TDengine 3.3.0.0 tmq raw data | - | -| v3.5.3 | 重构 taosWS | - | -| v3.5.2 | websocket 压缩和优化消息订阅性能 | 3.2.3.0 及更高版本 | -| v3.5.1 | 原生 stmt 查询和 geometry 类型支持 | 3.2.1.0 及更高版本 | -| v3.5.0 | 获取消费进度及按照指定进度开始消费 | 3.0.5.0 及更高版本 | -| v3.3.1 | 基于 websocket 的 schemaless 协议写入 | 3.0.4.1 及更高版本 | -| v3.1.0 | 提供贴近 kafka 的订阅 api | - | -| v3.0.4 | 新增 request id 相关接口 | 3.0.2.2 及更高版本 | -| v3.0.3 | 基于 websocket 的 statement 写入 | - | -| v3.0.2 | 基于 websocket 的数据查询和写入 | 3.0.1.5 及更高版本 | -| v3.0.1 | 基于 websocket 的消息订阅 | - | -| v3.0.0 | 适配 TDengine 3.0 查询和写入 | 3.0.0.0 及更高版本 | +| driver-go 版本 | 主要变化 | TDengine 版本 | +|--------------|--------------------------------------------|---------------| +| v3.6.0 | stmt2 原生接口,DSN 支持密码包含特殊字符(url.QueryEscape) | 3.3.5.0 及更高版本 | +| v3.5.8 | 修复空指针异常 | - | +| v3.5.7 | taosWS 和 taosRestful 支持传入 request id | - | +| v3.5.6 | 提升 websocket 查询和写入性能 | 3.3.2.0 及更高版本 | +| v3.5.5 | restful 支持跳过 ssl 证书检查 | - | +| v3.5.4 | 兼容 TDengine 3.3.0.0 tmq raw data | - | +| v3.5.3 | 重构 taosWS | - | +| v3.5.2 | websocket 压缩和优化消息订阅性能 | 3.2.3.0 及更高版本 | +| v3.5.1 | 原生 stmt 查询和 geometry 类型支持 | 3.2.1.0 及更高版本 | +| v3.5.0 | 获取消费进度及按照指定进度开始消费 | 3.0.5.0 及更高版本 | +| v3.3.1 | 基于 websocket 的 schemaless 协议写入 | 3.0.4.1 及更高版本 | +| v3.1.0 | 提供贴近 kafka 的订阅 api | - | +| v3.0.4 | 新增 request id 相关接口 | 3.0.2.2 及更高版本 | +| v3.0.3 | 基于 websocket 的 statement 写入 | - | +| v3.0.2 | 基于 websocket 的数据查询和写入 | 3.0.1.5 及更高版本 | +| v3.0.1 | 基于 websocket 的消息订阅 | - | +| v3.0.0 | 适配 TDengine 3.0 查询和写入 | 3.0.0.0 及更高版本 | ## 异常和错误码 @@ -137,6 +138,8 @@ WKB规范请参考[Well-Known Binary (WKB)](https://libgeos.org/specifications/w username:password@protocol(address)/dbname?param=value ``` +当密码中包含特殊字符时,需要使用 `url.QueryEscape` 进行转义。 + ##### 原生连接 导入驱动: From 4167f0d40f1e461cbe94858a7a0adb84dc26ca16 Mon Sep 17 00:00:00 2001 From: t_max <1172915550@qq.com> Date: Mon, 30 Dec 2024 11:06:33 +0800 Subject: [PATCH 3/3] test: add go stmt2 example test --- docs/examples/go/go.mod | 2 +- docs/examples/go/go.sum | 4 ++-- tests/docs-examples-test/go.sh | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/examples/go/go.mod b/docs/examples/go/go.mod index ed8fde2d9f..2dd5d4ec2b 100644 --- a/docs/examples/go/go.mod +++ b/docs/examples/go/go.mod @@ -2,7 +2,7 @@ module goexample go 1.17 -require github.com/taosdata/driver-go/v3 v3.5.6 +require github.com/taosdata/driver-go/v3 v3.6.0 require ( github.com/google/uuid v1.3.0 // indirect diff --git a/docs/examples/go/go.sum b/docs/examples/go/go.sum index 61841429ee..ee2ad55588 100644 --- a/docs/examples/go/go.sum +++ b/docs/examples/go/go.sum @@ -18,8 +18,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/taosdata/driver-go/v3 v3.5.6 h1:LDVtMyT3B9p2VREsd5KKM91D4Y7P4kSdh2SQumXi8bk= -github.com/taosdata/driver-go/v3 v3.5.6/go.mod h1:H2vo/At+rOPY1aMzUV9P49SVX7NlXb3LAbKw+MCLrmU= +github.com/taosdata/driver-go/v3 v3.6.0 h1:4dRXMl01DhIS5xBXUvtkkB+MjL8g64zN674xKd+ojTE= +github.com/taosdata/driver-go/v3 v3.6.0/go.mod h1:H2vo/At+rOPY1aMzUV9P49SVX7NlXb3LAbKw+MCLrmU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tests/docs-examples-test/go.sh b/tests/docs-examples-test/go.sh index 606265435d..fa02b33b10 100644 --- a/tests/docs-examples-test/go.sh +++ b/tests/docs-examples-test/go.sh @@ -61,6 +61,11 @@ check_transactions || exit 1 reset_cache || exit 1 go run ./stmt/ws/main.go +taos -s "drop database if exists power" +check_transactions || exit 1 +reset_cache || exit 1 +go run ./stmt2/native/main.go + taos -s "drop database if exists power" check_transactions || exit 1 reset_cache || exit 1