|
17 | 17 | - [Use `sql.Named` in a builder](#use-sqlnamed-in-a-builder) |
18 | 18 | - [Argument modifiers](#argument-modifiers) |
19 | 19 | - [Freestyle builder](#freestyle-builder) |
| 20 | + - [Clone builders](#clone-builders) |
20 | 21 | - [Using special syntax to build SQL](#using-special-syntax-to-build-sql) |
21 | 22 | - [Interpolate `args` in the `sql`](#interpolate-args-in-the-sql) |
22 | 23 | - [License](#license) |
@@ -381,6 +382,51 @@ fmt.Println(args) |
381 | 382 | // [1 2] |
382 | 383 | ``` |
383 | 384 |
|
| 385 | +### Clone builders |
| 386 | + |
| 387 | +The `Clone` methods make any builder reusable as a template. You can create a partially initialized builder once (even as a global), then call `Clone()` to get an independent copy to customize per request. This avoids repeated setup while keeping shared templates immutable and safe for concurrent use. |
| 388 | + |
| 389 | +Supported builders with `Clone`: |
| 390 | + |
| 391 | +- [CreateTableBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#CreateTableBuilder) |
| 392 | +- [CTEBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#CTEBuilder) |
| 393 | +- [CTEQueryBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#CTEQueryBuilder) |
| 394 | +- [DeleteBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#DeleteBuilder) |
| 395 | +- [InsertBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#InsertBuilder) |
| 396 | +- [SelectBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#SelectBuilder) |
| 397 | +- [UnionBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#UnionBuilder) |
| 398 | +- [UpdateBuilder](https://pkg.go.dev/github.com/huandu/go-sqlbuilder#UpdateBuilder) |
| 399 | + |
| 400 | +Example: define a global SELECT template and clone it per call |
| 401 | + |
| 402 | +```go |
| 403 | +package yourpkg |
| 404 | + |
| 405 | +import "github.com/huandu/go-sqlbuilder" |
| 406 | + |
| 407 | +// Global template — safe to reuse by cloning. |
| 408 | +var baseUserSelect = sqlbuilder.NewSelectBuilder(). |
| 409 | + Select("id", "name", "email"). |
| 410 | + From("users"). |
| 411 | + Where("deleted_at IS NULL") |
| 412 | + |
| 413 | +func ListActiveUsers(limit, offset int) (string, []interface{}) { |
| 414 | + sb := baseUserSelect.Clone() // independent copy |
| 415 | + sb.OrderBy("id").Asc() |
| 416 | + sb.Limit(limit).Offset(offset) |
| 417 | + return sb.Build() |
| 418 | +} |
| 419 | + |
| 420 | +func GetActiveUserByID(id int64) (string, []interface{}) { |
| 421 | + sb := baseUserSelect.Clone() // start from the same template |
| 422 | + sb.Where(sb.Equal("id", id)) |
| 423 | + sb.Limit(1) |
| 424 | + return sb.Build() |
| 425 | +} |
| 426 | +``` |
| 427 | + |
| 428 | +The same template pattern applies to other builders. For example, keep a base `UpdateBuilder` with the table and common `SET` clauses, or a base `CTEBuilder` defining reusable CTEs, then `Clone()` and add query-specific `WHERE`/`ORDER BY`/`LIMIT`/`RETURNING` as needed. |
| 429 | + |
384 | 430 | ### Using special syntax to build SQL |
385 | 431 |
|
386 | 432 | The `sqlbuilder` package incorporates special syntax for representing uncompiled SQL internally. To leverage this syntax for developing customized tools, the `Build` function can be utilized to compile it with the necessary arguments. |
|
0 commit comments