mirror of https://github.com/VinGarcia/ksql.git
Update README and the README build script
parent
e7896dc16e
commit
d6aa694f82
6
Makefile
6
Makefile
|
@ -3,7 +3,7 @@ path=./...
|
||||||
|
|
||||||
GOBIN=$(shell go env GOPATH)/bin
|
GOBIN=$(shell go env GOPATH)/bin
|
||||||
|
|
||||||
TIME=1s
|
TIME=5s
|
||||||
|
|
||||||
test: setup go-mod-tidy
|
test: setup go-mod-tidy
|
||||||
$(GOBIN)/richgo test $(path) $(args)
|
$(GOBIN)/richgo test $(path) $(args)
|
||||||
|
@ -18,7 +18,9 @@ bench: go-mod-tidy
|
||||||
@make --no-print-directory -C benchmarks TIME=$(TIME) | tee benchmark.tmp
|
@make --no-print-directory -C benchmarks TIME=$(TIME) | tee benchmark.tmp
|
||||||
@echo "Benchmark executed at: $$(date --iso)" | tee -a benchmark.tmp
|
@echo "Benchmark executed at: $$(date --iso)" | tee -a benchmark.tmp
|
||||||
@echo "Benchmark executed on commit: $$(git rev-parse HEAD)" | tee -a benchmark.tmp
|
@echo "Benchmark executed on commit: $$(git rev-parse HEAD)" | tee -a benchmark.tmp
|
||||||
go run scripts/build-readme-from-template.go readme.template.md benchmark.tmp
|
|
||||||
|
readme: benchmark.tmp README.template.md
|
||||||
|
go run scripts/build-readme-from-template.go README.template.md examples/crud/crud.go benchmark.tmp
|
||||||
|
|
||||||
lint: setup go-mod-tidy
|
lint: setup go-mod-tidy
|
||||||
@$(GOBIN)/staticcheck $(path) $(args)
|
@$(GOBIN)/staticcheck $(path) $(args)
|
||||||
|
|
96
README.md
96
README.md
|
@ -3,7 +3,6 @@
|
||||||
[](https://pkg.go.dev/github.com/vingarcia/ksql)
|
[](https://pkg.go.dev/github.com/vingarcia/ksql)
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# KSQL the Keep it Simple SQL library
|
# KSQL the Keep it Simple SQL library
|
||||||
|
|
||||||
KSQL was created to offer an actually simple and satisfactory
|
KSQL was created to offer an actually simple and satisfactory
|
||||||
|
@ -150,23 +149,35 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/vingarcia/ksql"
|
"github.com/vingarcia/ksql"
|
||||||
"github.com/vingarcia/ksql/adapters/ksqlite3"
|
"github.com/vingarcia/ksql/adapters/ksqlite3"
|
||||||
"github.com/vingarcia/ksql/nullable"
|
"github.com/vingarcia/ksql/nullable"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User ...
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `ksql:"id"`
|
ID int `ksql:"id"`
|
||||||
Name string `ksql:"name"`
|
Name string `ksql:"name"`
|
||||||
Age int `ksql:"age"`
|
Age int `ksql:"age"`
|
||||||
|
|
||||||
// This field will be saved as JSON in the database
|
// The following attributes are making use of the KSQL Modifiers,
|
||||||
|
// you can find more about them on our Wiki:
|
||||||
|
//
|
||||||
|
// - https://github.com/VinGarcia/ksql/wiki/Modifiers
|
||||||
|
//
|
||||||
|
|
||||||
|
// The `json` modifier will save the address as JSON in the database
|
||||||
Address Address `ksql:"address,json"`
|
Address Address `ksql:"address,json"`
|
||||||
|
|
||||||
|
// The timeNowUTC modifier will set this field to `time.Now().UTC()` before saving it:
|
||||||
|
UpdatedAt time.Time `ksql:"updated_at,timeNowUTC"`
|
||||||
|
|
||||||
|
// The timeNowUTC/skipUpdates modifier will set this field to `time.Now().UTC()` only
|
||||||
|
// when first creating it and ignore it during updates.
|
||||||
|
CreatedAt time.Time `ksql:"created_at,timeNowUTC/skipUpdates"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PartialUpdateUser ...
|
|
||||||
type PartialUpdateUser struct {
|
type PartialUpdateUser struct {
|
||||||
ID int `ksql:"id"`
|
ID int `ksql:"id"`
|
||||||
Name *string `ksql:"name"`
|
Name *string `ksql:"name"`
|
||||||
|
@ -174,7 +185,6 @@ type PartialUpdateUser struct {
|
||||||
Address *Address `ksql:"address,json"`
|
Address *Address `ksql:"address,json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address ...
|
|
||||||
type Address struct {
|
type Address struct {
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
|
@ -211,7 +221,9 @@ func main() {
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
age INTEGER,
|
age INTEGER,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
address BLOB
|
address BLOB,
|
||||||
|
created_at DATETIME,
|
||||||
|
updated_at DATETIME
|
||||||
)`)
|
)`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
|
@ -373,43 +385,43 @@ goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
pkg: github.com/vingarcia/ksql/benchmarks
|
pkg: github.com/vingarcia/ksql/benchmarks
|
||||||
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
|
cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
|
||||||
BenchmarkInsert/ksql/sql-adapter/insert-one-12 9256 626985 ns/op
|
BenchmarkInsert/ksql/sql-adapter/insert-one-12 9373 658434 ns/op
|
||||||
BenchmarkInsert/ksql/pgx-adapter/insert-one-12 11056 548748 ns/op
|
BenchmarkInsert/ksql/pgx-adapter/insert-one-12 10000 571623 ns/op
|
||||||
BenchmarkInsert/sql/insert-one-12 9565 623659 ns/op
|
BenchmarkInsert/sql/insert-one-12 9423 627719 ns/op
|
||||||
BenchmarkInsert/sql/prep-stmt/insert-one-12 10000 541058 ns/op
|
BenchmarkInsert/sql/prep-stmt/insert-one-12 10000 559441 ns/op
|
||||||
BenchmarkInsert/sqlx/insert-one-12 9319 637775 ns/op
|
BenchmarkInsert/sqlx/insert-one-12 9651 637823 ns/op
|
||||||
BenchmarkInsert/sqlx/prep-stmt/insert-one-12 10000 549806 ns/op
|
BenchmarkInsert/sqlx/prep-stmt/insert-one-12 10000 574260 ns/op
|
||||||
BenchmarkInsert/pgxpool/insert-one-12 10000 546349 ns/op
|
BenchmarkInsert/pgxpool/insert-one-12 10000 568112 ns/op
|
||||||
BenchmarkInsert/gorm/insert-one-12 8859 675650 ns/op
|
BenchmarkInsert/gorm/insert-one-12 8504 696791 ns/op
|
||||||
BenchmarkInsert/sqlc/insert-one-12 9889 634589 ns/op
|
BenchmarkInsert/sqlc/insert-one-12 9504 662484 ns/op
|
||||||
BenchmarkInsert/sqlc/prep-stmt/insert-one-12 10000 552079 ns/op
|
BenchmarkInsert/sqlc/prep-stmt/insert-one-12 10000 568876 ns/op
|
||||||
BenchmarkInsert/sqlboiler/insert-one-12 9536 633515 ns/op
|
BenchmarkInsert/sqlboiler/insert-one-12 9298 667913 ns/op
|
||||||
BenchmarkQuery/ksql/sql-adapter/single-row-12 41222 144799 ns/op
|
BenchmarkQuery/ksql/sql-adapter/single-row-12 39939 150412 ns/op
|
||||||
BenchmarkQuery/ksql/sql-adapter/multiple-rows-12 38523 156556 ns/op
|
BenchmarkQuery/ksql/sql-adapter/multiple-rows-12 35901 156905 ns/op
|
||||||
BenchmarkQuery/ksql/pgx-adapter/single-row-12 85074 72465 ns/op
|
BenchmarkQuery/ksql/pgx-adapter/single-row-12 83677 72461 ns/op
|
||||||
BenchmarkQuery/ksql/pgx-adapter/multiple-rows-12 70690 84502 ns/op
|
BenchmarkQuery/ksql/pgx-adapter/multiple-rows-12 71182 89788 ns/op
|
||||||
BenchmarkQuery/sql/single-row-12 41802 144467 ns/op
|
BenchmarkQuery/sql/single-row-12 40140 147991 ns/op
|
||||||
BenchmarkQuery/sql/multiple-rows-12 39248 147765 ns/op
|
BenchmarkQuery/sql/multiple-rows-12 39210 154899 ns/op
|
||||||
BenchmarkQuery/sql/prep-stmt/single-row-12 80530 71376 ns/op
|
BenchmarkQuery/sql/prep-stmt/single-row-12 82580 76769 ns/op
|
||||||
BenchmarkQuery/sql/prep-stmt/multiple-rows-12 76730 77769 ns/op
|
BenchmarkQuery/sql/prep-stmt/multiple-rows-12 76880 77115 ns/op
|
||||||
BenchmarkQuery/sqlx/single-row-12 41960 146817 ns/op
|
BenchmarkQuery/sqlx/single-row-12 42120 144501 ns/op
|
||||||
BenchmarkQuery/sqlx/multiple-rows-12 39349 152887 ns/op
|
BenchmarkQuery/sqlx/multiple-rows-12 39396 155193 ns/op
|
||||||
BenchmarkQuery/sqlx/prep-stmt/single-row-12 81045 73004 ns/op
|
BenchmarkQuery/sqlx/prep-stmt/single-row-12 84583 72094 ns/op
|
||||||
BenchmarkQuery/sqlx/prep-stmt/multiple-rows-12 75256 78604 ns/op
|
BenchmarkQuery/sqlx/prep-stmt/multiple-rows-12 75465 78078 ns/op
|
||||||
BenchmarkQuery/pgxpool/single-row-12 82630 72241 ns/op
|
BenchmarkQuery/pgxpool/single-row-12 87724 72368 ns/op
|
||||||
BenchmarkQuery/pgxpool/multiple-rows-12 81619 74408 ns/op
|
BenchmarkQuery/pgxpool/multiple-rows-12 77012 77658 ns/op
|
||||||
BenchmarkQuery/gorm/single-row-12 76700 78651 ns/op
|
BenchmarkQuery/gorm/single-row-12 74268 80303 ns/op
|
||||||
BenchmarkQuery/gorm/multiple-rows-12 62342 95746 ns/op
|
BenchmarkQuery/gorm/multiple-rows-12 63933 100220 ns/op
|
||||||
BenchmarkQuery/sqlc/single-row-12 41563 146143 ns/op
|
BenchmarkQuery/sqlc/single-row-12 39211 149178 ns/op
|
||||||
BenchmarkQuery/sqlc/multiple-rows-12 40240 149534 ns/op
|
BenchmarkQuery/sqlc/multiple-rows-12 38748 153076 ns/op
|
||||||
BenchmarkQuery/sqlc/prep-stmt/single-row-12 83230 72397 ns/op
|
BenchmarkQuery/sqlc/prep-stmt/single-row-12 83739 76111 ns/op
|
||||||
BenchmarkQuery/sqlc/prep-stmt/multiple-rows-12 79408 78645 ns/op
|
BenchmarkQuery/sqlc/prep-stmt/multiple-rows-12 75025 80939 ns/op
|
||||||
BenchmarkQuery/sqlboiler/single-row-12 65866 93841 ns/op
|
BenchmarkQuery/sqlboiler/single-row-12 63660 95534 ns/op
|
||||||
BenchmarkQuery/sqlboiler/multiple-rows-12 65091 94486 ns/op
|
BenchmarkQuery/sqlboiler/multiple-rows-12 64256 98597 ns/op
|
||||||
PASS
|
PASS
|
||||||
ok github.com/vingarcia/ksql/benchmarks 226.109s
|
ok github.com/vingarcia/ksql/benchmarks 224.967s
|
||||||
Benchmark executed at: 2022-11-13
|
Benchmark executed at: 2022-12-04
|
||||||
Benchmark executed on commit: 5bfb5cd92affae29dab3499b07fcd36b70a20057
|
Benchmark executed on commit: e7896dc16ef8ede091e5d1568bd53096af65a1ef
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running the KSQL tests (for contributors)
|
## Running the KSQL tests (for contributors)
|
||||||
|
|
|
@ -3,16 +3,20 @@
|
||||||
[](https://pkg.go.dev/github.com/vingarcia/ksql)
|
[](https://pkg.go.dev/github.com/vingarcia/ksql)
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
# KSQL the Keep it Simple SQL library
|
# KSQL the Keep it Simple SQL library
|
||||||
|
|
||||||
KSQL was created to offer an actually simple and satisfactory
|
KSQL was created to offer an actually simple and satisfactory
|
||||||
tool for interacting with SQL Databases in Golang.
|
tool for interacting with SQL Databases in Golang.
|
||||||
|
|
||||||
The core idea on KSQL is to offer an easy to use interface,
|
The core goal of KSQL is not to offer new features that
|
||||||
the actual communication with the database is decoupled so we can use
|
are unavailable on other libraries (although we do have some),
|
||||||
KSQL on top of `pgx`, `database/sql` and possibly other tools.
|
but to offer a well-thought and well-planned API so that users
|
||||||
You can even create you own backend adapter for KSQL which is
|
have an easier time, learning, debugging, and avoiding common pitfalls.
|
||||||
|
|
||||||
|
KSQL is also decoupled from its backend so that
|
||||||
|
the actual communication with the database is performed by
|
||||||
|
well-known and trusted technologies, namely: `pgx` and `database/sql`.
|
||||||
|
You can even create your own backend adapter for KSQL which is
|
||||||
useful in some situations.
|
useful in some situations.
|
||||||
|
|
||||||
In this README you will find examples for "Getting Started" with the library,
|
In this README you will find examples for "Getting Started" with the library,
|
||||||
|
@ -140,185 +144,7 @@ which is also available [here](./examples/crud/crud.go)
|
||||||
if you want to compile it yourself.
|
if you want to compile it yourself.
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
package main
|
{{ .crudExample -}}
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/vingarcia/ksql"
|
|
||||||
"github.com/vingarcia/ksql/adapters/ksqlite3"
|
|
||||||
"github.com/vingarcia/ksql/nullable"
|
|
||||||
)
|
|
||||||
|
|
||||||
// User ...
|
|
||||||
type User struct {
|
|
||||||
ID int `ksql:"id"`
|
|
||||||
Name string `ksql:"name"`
|
|
||||||
Age int `ksql:"age"`
|
|
||||||
|
|
||||||
// This field will be saved as JSON in the database
|
|
||||||
Address Address `ksql:"address,json"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// PartialUpdateUser ...
|
|
||||||
type PartialUpdateUser struct {
|
|
||||||
ID int `ksql:"id"`
|
|
||||||
Name *string `ksql:"name"`
|
|
||||||
Age *int `ksql:"age"`
|
|
||||||
Address *Address `ksql:"address,json"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Address ...
|
|
||||||
type Address struct {
|
|
||||||
State string `json:"state"`
|
|
||||||
City string `json:"city"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UsersTable informs KSQL the name of the table and that it can
|
|
||||||
// use the default value for the primary key column name: "id"
|
|
||||||
var UsersTable = ksql.NewTable("users")
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// The available adapters are:
|
|
||||||
// - kpgx.New(ctx, connURL, ksql.Config{})
|
|
||||||
// - kmysql.New(ctx, connURL, ksql.Config{})
|
|
||||||
// - ksqlserver.New(ctx, connURL, ksql.Config{})
|
|
||||||
// - ksqlite3.New(ctx, connURL, ksql.Config{})
|
|
||||||
//
|
|
||||||
// For more detailed examples see:
|
|
||||||
// - `./examples/all_adapters/all_adapters.go`
|
|
||||||
//
|
|
||||||
// In this example we'll use sqlite3:
|
|
||||||
db, err := ksqlite3.New(ctx, "/tmp/hello.sqlite", ksql.Config{
|
|
||||||
MaxOpenConns: 1,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
// In the definition below, please note that BLOB is
|
|
||||||
// the only type we can use in sqlite for storing JSON.
|
|
||||||
_, err = db.Exec(ctx, `CREATE TABLE IF NOT EXISTS users (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
age INTEGER,
|
|
||||||
name TEXT,
|
|
||||||
address BLOB
|
|
||||||
)`)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
var alison = User{
|
|
||||||
Name: "Alison",
|
|
||||||
Age: 22,
|
|
||||||
Address: Address{
|
|
||||||
State: "MG",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
err = db.Insert(ctx, UsersTable, &alison)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Println("Alison ID:", alison.ID)
|
|
||||||
|
|
||||||
// Inserting inline:
|
|
||||||
err = db.Insert(ctx, UsersTable, &User{
|
|
||||||
Name: "Cristina",
|
|
||||||
Age: 27,
|
|
||||||
Address: Address{
|
|
||||||
State: "SP",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deleting Alison:
|
|
||||||
err = db.Delete(ctx, UsersTable, alison.ID)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieving Cristina, note that if you omit the SELECT part of the query
|
|
||||||
// KSQL will build it for you (efficiently) based on the fields from the struct:
|
|
||||||
var cris User
|
|
||||||
err = db.QueryOne(ctx, &cris, "FROM users WHERE name = ? ORDER BY id", "Cristina")
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
fmt.Printf("Cristina: %#v\n", cris)
|
|
||||||
|
|
||||||
// Updating all fields from Cristina:
|
|
||||||
cris.Name = "Cris"
|
|
||||||
err = db.Patch(ctx, UsersTable, cris)
|
|
||||||
|
|
||||||
// Changing the age of Cristina but not touching any other fields:
|
|
||||||
|
|
||||||
// Partial update technique 1:
|
|
||||||
err = db.Patch(ctx, UsersTable, struct {
|
|
||||||
ID int `ksql:"id"`
|
|
||||||
Age int `ksql:"age"`
|
|
||||||
}{ID: cris.ID, Age: 28})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Partial update technique 2:
|
|
||||||
err = db.Patch(ctx, UsersTable, PartialUpdateUser{
|
|
||||||
ID: cris.ID,
|
|
||||||
Age: nullable.Int(28), // (just a pointer to an int, if null it won't be updated)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listing first 10 users from the database
|
|
||||||
// (each time you run this example a new Cristina is created)
|
|
||||||
//
|
|
||||||
// Note: Using this function it is recommended to set a LIMIT, since
|
|
||||||
// not doing so can load too many users on your computer's memory or
|
|
||||||
// cause an Out Of Memory Kill.
|
|
||||||
//
|
|
||||||
// If you need to query very big numbers of users we recommend using
|
|
||||||
// the `QueryChunks` function.
|
|
||||||
var users []User
|
|
||||||
err = db.Query(ctx, &users, "FROM users LIMIT 10")
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Users: %#v\n", users)
|
|
||||||
|
|
||||||
// Making transactions:
|
|
||||||
err = db.Transaction(ctx, func(db ksql.Provider) error {
|
|
||||||
var cris2 User
|
|
||||||
err = db.QueryOne(ctx, &cris2, "FROM users WHERE id = ?", cris.ID)
|
|
||||||
if err != nil {
|
|
||||||
// This will cause an automatic rollback:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = db.Patch(ctx, UsersTable, PartialUpdateUser{
|
|
||||||
ID: cris2.ID,
|
|
||||||
Age: nullable.Int(29),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
// This will also cause an automatic rollback and then panic again
|
|
||||||
// so that we don't hide the panic inside the KSQL library
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commits the transaction
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Benchmark Comparison
|
## Benchmark Comparison
|
||||||
|
@ -362,7 +188,7 @@ Without further ado, here are the results:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ make bench TIME=5s
|
$ make bench TIME=5s
|
||||||
{{- .benchmark -}}
|
{{ .benchmark -}}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running the KSQL tests (for contributors)
|
## Running the KSQL tests (for contributors)
|
|
@ -3,23 +3,35 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/vingarcia/ksql"
|
"github.com/vingarcia/ksql"
|
||||||
"github.com/vingarcia/ksql/adapters/ksqlite3"
|
"github.com/vingarcia/ksql/adapters/ksqlite3"
|
||||||
"github.com/vingarcia/ksql/nullable"
|
"github.com/vingarcia/ksql/nullable"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User ...
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int `ksql:"id"`
|
ID int `ksql:"id"`
|
||||||
Name string `ksql:"name"`
|
Name string `ksql:"name"`
|
||||||
Age int `ksql:"age"`
|
Age int `ksql:"age"`
|
||||||
|
|
||||||
// This field will be saved as JSON in the database
|
// The following attributes are making use of the KSQL Modifiers,
|
||||||
|
// you can find more about them on our Wiki:
|
||||||
|
//
|
||||||
|
// - https://github.com/VinGarcia/ksql/wiki/Modifiers
|
||||||
|
//
|
||||||
|
|
||||||
|
// The `json` modifier will save the address as JSON in the database
|
||||||
Address Address `ksql:"address,json"`
|
Address Address `ksql:"address,json"`
|
||||||
|
|
||||||
|
// The timeNowUTC modifier will set this field to `time.Now().UTC()` before saving it:
|
||||||
|
UpdatedAt time.Time `ksql:"updated_at,timeNowUTC"`
|
||||||
|
|
||||||
|
// The timeNowUTC/skipUpdates modifier will set this field to `time.Now().UTC()` only
|
||||||
|
// when first creating it and ignore it during updates.
|
||||||
|
CreatedAt time.Time `ksql:"created_at,timeNowUTC/skipUpdates"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PartialUpdateUser ...
|
|
||||||
type PartialUpdateUser struct {
|
type PartialUpdateUser struct {
|
||||||
ID int `ksql:"id"`
|
ID int `ksql:"id"`
|
||||||
Name *string `ksql:"name"`
|
Name *string `ksql:"name"`
|
||||||
|
@ -27,13 +39,12 @@ type PartialUpdateUser struct {
|
||||||
Address *Address `ksql:"address,json"`
|
Address *Address `ksql:"address,json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address ...
|
|
||||||
type Address struct {
|
type Address struct {
|
||||||
State string `json:"state"`
|
State string `json:"state"`
|
||||||
City string `json:"city"`
|
City string `json:"city"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsersTable informs ksql the name of the table and that it can
|
// UsersTable informs KSQL the name of the table and that it can
|
||||||
// use the default value for the primary key column name: "id"
|
// use the default value for the primary key column name: "id"
|
||||||
var UsersTable = ksql.NewTable("users")
|
var UsersTable = ksql.NewTable("users")
|
||||||
|
|
||||||
|
@ -64,7 +75,9 @@ func main() {
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
age INTEGER,
|
age INTEGER,
|
||||||
name TEXT,
|
name TEXT,
|
||||||
address BLOB
|
address BLOB,
|
||||||
|
created_at DATETIME,
|
||||||
|
updated_at DATETIME
|
||||||
)`)
|
)`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
|
@ -102,7 +115,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieving Cristina, note that if you omit the SELECT part of the query
|
// Retrieving Cristina, note that if you omit the SELECT part of the query
|
||||||
// ksql will build it for you (efficiently) based on the fields from the struct:
|
// KSQL will build it for you (efficiently) based on the fields from the struct:
|
||||||
var cris User
|
var cris User
|
||||||
err = db.QueryOne(ctx, &cris, "FROM users WHERE name = ? ORDER BY id", "Cristina")
|
err = db.QueryOne(ctx, &cris, "FROM users WHERE name = ? ORDER BY id", "Cristina")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,14 +7,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 3 {
|
if len(os.Args) < 4 {
|
||||||
log.Fatalf(
|
log.Fatalf(
|
||||||
"USAGE: go run scripts/build-readme-from-template.go TEMPLATE_FILEPATH BENCHMARK_FILEPATH",
|
"USAGE: go run scripts/build-readme-from-template.go PATH_TO_TEMPLATE PATH_TO_CRUD_EXAMPLE PATH_TO_BENCHMARK",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
templateFilepath := os.Args[1]
|
templateFilepath := os.Args[1]
|
||||||
benchmarkFilepath := os.Args[2]
|
crudExampleFilepath := os.Args[2]
|
||||||
|
benchmarkFilepath := os.Args[3]
|
||||||
|
|
||||||
data, err := os.ReadFile(templateFilepath)
|
data, err := os.ReadFile(templateFilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -26,6 +27,11 @@ func main() {
|
||||||
log.Fatalf("unable to parse README template '%s': %s", templateFilepath, err)
|
log.Fatalf("unable to parse README template '%s': %s", templateFilepath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crudExample, err := os.ReadFile(crudExampleFilepath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("unable to read benchmark results '%s': %s", benchmarkFilepath, err)
|
||||||
|
}
|
||||||
|
|
||||||
benchmark, err := os.ReadFile(benchmarkFilepath)
|
benchmark, err := os.ReadFile(benchmarkFilepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("unable to read benchmark results '%s': %s", benchmarkFilepath, err)
|
log.Fatalf("unable to read benchmark results '%s': %s", benchmarkFilepath, err)
|
||||||
|
@ -37,7 +43,8 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.Execute(f, map[string]interface{}{
|
err = t.Execute(f, map[string]interface{}{
|
||||||
"benchmark": string(benchmark),
|
"crudExample": string(crudExample),
|
||||||
|
"benchmark": string(benchmark),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("error executing template file: %s", err)
|
log.Fatalf("error executing template file: %s", err)
|
||||||
|
|
Loading…
Reference in New Issue