diff --git a/coredb/txengine/tx_engine.go b/coredb/txengine/tx_engine.go index 6bb0168..c9637f1 100644 --- a/coredb/txengine/tx_engine.go +++ b/coredb/txengine/tx_engine.go @@ -7,8 +7,6 @@ import ( "fmt" "github.com/olachat/gola/v2/coredb" - "github.com/olachat/gola/v2/golalib/testdata/blogs" - "github.com/olachat/gola/v2/golalib/testdata/users" ) type TypedTx[T any] sql.Tx @@ -50,28 +48,6 @@ func StartTx(ctx context.Context, tx *sql.Tx, fn func(ctx context.Context, sqlTx return err } -func Example() { - ctxOuter := context.Background() - tx, _ := coredb.BeginTx(ctxOuter, "test_db", &coredb.DefaultTxOpts) - var count int - _ = StartTx(ctxOuter, tx, func(ctx context.Context, sqlTx *sql.Tx) error { - userRec, err := WithTypedTx[users.User](sqlTx).FindOne(ctx, users.TableName, coredb.NewWhere("where uid=?", 1)) - if err != nil { - return fmt.Errorf("findOne user uid:%d failed: %w", 1, err) - } - if userRec == nil { - return fmt.Errorf("user:%d not found", 1) - } - ct, err := WithTx(sqlTx).QueryInt(ctx, blogs.DBName, "select count(*) from blogs") - if err != nil { - return fmt.Errorf("QueryInt error: %w", err) - } - count = ct - return nil - }) - fmt.Println(count) -} - // FindOne returns a row from given table type with where query. // If no rows found, *T will be nil. No error will be returned. func (o *TypedTx[T]) FindOne(ctx context.Context, tableName string, where coredb.WhereQuery) (*T, error) { diff --git a/go.mod b/go.mod index b1723f1..3feaf08 100644 --- a/go.mod +++ b/go.mod @@ -8,16 +8,17 @@ replace github.com/jordan-bonecutter/goption v1.0.1 => github.com/yinloo-ola/gop require ( github.com/blastrain/vitess-sqlparser v0.0.0-20201030050434-a139afbb1aba - github.com/go-sql-driver/mysql v1.7.0 + github.com/go-sql-driver/mysql v1.7.2-0.20231213112541-0004702b931d github.com/jordan-bonecutter/goption v1.0.1 github.com/mitchellh/cli v1.1.4 github.com/pkg/errors v0.9.1 github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.1 - golang.org/x/text v0.7.0 + github.com/stretchr/testify v1.8.2 + golang.org/x/text v0.13.0 ) require ( + filippo.io/edwards25519 v1.1.0 // indirect github.com/Masterminds/goutils v1.1.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.0 // indirect @@ -25,12 +26,15 @@ require ( github.com/bgentry/speakeasy v0.1.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dolthub/vitess v0.0.0-20220603212614-514e62ec66cd // indirect + github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 // indirect + github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e // indirect + github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 // indirect + github.com/dolthub/vitess v0.0.0-20230823204737-4a21a94e90c3 // indirect github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/go-kit/kit v0.10.0 // indirect + github.com/gocraft/dbr/v2 v2.7.2 // indirect github.com/golang/protobuf v1.5.2 // indirect - github.com/google/flatbuffers v2.0.6+incompatible // indirect github.com/google/uuid v1.3.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -48,37 +52,38 @@ require ( github.com/mitchellh/hashstructure v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect - github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 // indirect - github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/posener/complete v1.1.1 // indirect - github.com/shopspring/decimal v1.2.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/src-d/go-oniguruma v1.1.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/tools v0.5.0 // indirect + github.com/tetratelabs/wazero v1.1.0 // indirect + github.com/tidwall/gjson v1.14.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + go.opentelemetry.io/otel v1.7.0 // indirect + go.opentelemetry.io/otel/trace v1.7.0 // indirect + golang.org/x/crypto v0.13.0 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect - google.golang.org/grpc v1.52.3 // indirect + google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/src-d/go-errors.v1 v1.0.0 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( - github.com/dolthub/go-mysql-server v0.12.0 // test + github.com/dolthub/go-mysql-server v0.17.0 // test github.com/google/go-cmp v0.5.9 // test ) diff --git a/go.sum b/go.sum index e1b4fdb..f7c1ee3 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,12 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -51,8 +55,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/Wuvist/go-mysql-server v0.10.1-0.20220815042140-eac9e0ba16d8 h1:hgbyN+AjAnCa4XRKlvZ2IoPtatE/9vy8CkwAJMhwwGo= -github.com/Wuvist/go-mysql-server v0.10.1-0.20220815042140-eac9e0ba16d8/go.mod h1:gvDEMITJQDVYDLR4XtcqEZx6rawTvMh2veM1bPsJC3I= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -100,9 +102,19 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= +github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dolthub/vitess v0.0.0-20220603212614-514e62ec66cd h1:2JUMs9E68P6LYJrm1yz4KcGnxiavqj3EeE+fRpVJaEI= -github.com/dolthub/vitess v0.0.0-20220603212614-514e62ec66cd/go.mod h1:5xfuFfpljoMYespuUmyl5zrHoK0Rl7Bm6yAsnJJJzuY= +github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2 h1:u3PMzfF8RkKd3lB9pZ2bfn0qEG+1Gms9599cr0REMww= +github.com/dolthub/flatbuffers/v23 v23.3.3-dh.2/go.mod h1:mIEZOHnFx4ZMQeawhw9rhsj+0zwQj7adVsnBX7t+eKY= +github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e h1:kPsT4a47cw1+y/N5SSCkma7FhAPw7KeGmD6c9PBZW9Y= +github.com/dolthub/go-icu-regex v0.0.0-20230524105445-af7e7991c97e/go.mod h1:KPUcpx070QOfJK1gNe0zx4pA5sicIK1GMikIGLKC168= +github.com/dolthub/go-mysql-server v0.17.0 h1:ztJjA001l6ZvutCPmwbSpegOlF0W0KKpzDk1m9SYq0s= +github.com/dolthub/go-mysql-server v0.17.0/go.mod h1:vSQ47leaIPTtvSLKo89D1FdYdypU5OH6VBV63B2MS8Y= +github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71 h1:bMGS25NWAGTEtT5tOBsCuCrlYnLRKpbJVJkDbrTRhwQ= +github.com/dolthub/jsonpath v0.0.2-0.20240227200619-19675ab05c71/go.mod h1:2/2zjLQ/JOOSbbSboojeg+cAwcRV0fDLzIiWch/lhqI= +github.com/dolthub/vitess v0.0.0-20230823204737-4a21a94e90c3 h1:lY3oQbYNMSVjT02n6f2M2H0u4icF6lGbS/IpWr27ti8= +github.com/dolthub/vitess v0.0.0-20230823204737-4a21a94e90c3/go.mod h1:IwjNXSQPymrja5pVqmfnYdcy7Uv7eNJNBPK/MEh9OOw= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= @@ -136,14 +148,23 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.2-0.20231213112541-0004702b931d h1:QQP1nE4qh5aHTGvI1LgOFxZYVxYoGeMfbNHikogPyoA= +github.com/go-sql-driver/mysql v1.7.2-0.20231213112541-0004702b931d/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gocraft/dbr/v2 v2.7.2 h1:ccUxMuz6RdZvD7VPhMRRMSS/ECF3gytPhPtcavjktHk= +github.com/gocraft/dbr/v2 v2.7.2/go.mod h1:5bCqyIXO5fYn3jEp/L06QF4K1siFdhxChMjdNu6YJrg= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -176,8 +197,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v2.0.6+incompatible h1:XHFReMv7nFFusa+CEokzWbzaYocKXI6C7hdU5Kgh9Lw= -github.com/google/flatbuffers v2.0.6+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -188,6 +207,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -262,6 +282,8 @@ github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -294,6 +316,8 @@ github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2t github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/strftime v1.0.4 h1:T1Rb9EPkAhgxKqbcMIPguPq8glqXTA1koF8n9BHElA8= github.com/lestrrat-go/strftime v1.0.4/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= @@ -309,6 +333,9 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= +github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -343,8 +370,6 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= -github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -353,7 +378,6 @@ github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= @@ -403,8 +427,9 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -414,9 +439,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -430,8 +454,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= -github.com/src-d/go-oniguruma v1.1.0 h1:EG+Nm5n2JqWUaCjtM0NtutPxU7ZN5Tp50GWrrV8bTww= -github.com/src-d/go-oniguruma v1.1.0/go.mod h1:chVbff8kcVtmrhxtZ3yBVLLquXbzCS6DrxQaAK/CeqM= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= @@ -447,10 +469,23 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= +github.com/tetratelabs/wazero v1.1.0/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -472,6 +507,10 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= +go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= +go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= +go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -482,6 +521,7 @@ go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -491,8 +531,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -526,8 +566,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -567,8 +607,7 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -588,8 +627,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -637,8 +676,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20180302201248-b7ef84aaf62a/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -647,8 +686,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -706,8 +745,8 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= -golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -800,8 +839,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -841,7 +880,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/golalib/golalib.go b/golalib/golalib.go index c033efe..841de44 100644 --- a/golalib/golalib.go +++ b/golalib/golalib.go @@ -190,6 +190,7 @@ func genORM(t *structs.Table) map[string][]byte { genFiles := map[string]string{ "00_struct.gogo": tableFolder + t.Name + ".go", "00_struct_ctx.gogo": tableFolder + t.Name + "_ctx.go", + "00_struct_tx.gogo": tableFolder + t.Name + "_tx.go", "01_struct_idx.gogo": tableFolder + t.Name + "_idx.go", "01_struct_idx_ctx.gogo": tableFolder + t.Name + "_idx_ctx.go", } diff --git a/golalib/testdata/account/account_tx.go b/golalib/testdata/account/account_tx.go new file mode 100644 index 0000000..31598f0 --- /dev/null +++ b/golalib/testdata/account/account_tx.go @@ -0,0 +1,128 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package account + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Account struct to `account` table with transaction +func (c *Account) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getUserIdForDB(), c.getTypeForDB(), c.getCountryCodeForDB(), c.getMoneyForDB()) + if err != nil { + return err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Account struct in `account` table with transaction +func (obj *Account) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Type.IsUpdated() { + updatedFields = append(updatedFields, "`type` = ?") + params = append(params, obj.getTypeForDB()) + } + if obj.Money.IsUpdated() { + updatedFields = append(updatedFields, "`money` = ?") + params = append(params, obj.getMoneyForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `account` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `country_code` = ?" + params = append(params, obj.GetUserId(), obj.GetCountryCode()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Account struct with given fields in `account` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Type: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`type` = ?") + params = append(params, c.getTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Money: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`money` = ?") + params = append(params, c.getMoneyForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `account` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `country_code` = ?" + params = append(params, obj.GetUserId(), obj.GetCountryCode()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/blogs/blogs_tx.go b/golalib/testdata/blogs/blogs_tx.go new file mode 100644 index 0000000..eacd119 --- /dev/null +++ b/golalib/testdata/blogs/blogs_tx.go @@ -0,0 +1,221 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package blogs + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Blog struct to `blogs` table with transaction +func (c *Blog) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getUserIdForDB(), c.getSlugForDB(), c.getTitleForDB(), c.getCategoryIdForDB(), c.getIsPinnedForDB(), c.getIsVipForDB(), c.getCountryForDB(), c.getCreatedAtForDB(), c.getUpdatedAtForDB(), c.getCountForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getUserIdForDB(), c.getSlugForDB(), c.getTitleForDB(), c.getCategoryIdForDB(), c.getIsPinnedForDB(), c.getIsVipForDB(), c.getCountryForDB(), c.getCreatedAtForDB(), c.getUpdatedAtForDB(), c.getCountForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = int(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Blog struct in `blogs` table with transaction +func (obj *Blog) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.UserId.IsUpdated() { + updatedFields = append(updatedFields, "`user_id` = ?") + params = append(params, obj.getUserIdForDB()) + } + if obj.Slug.IsUpdated() { + updatedFields = append(updatedFields, "`slug` = ?") + params = append(params, obj.getSlugForDB()) + } + if obj.Title.IsUpdated() { + updatedFields = append(updatedFields, "`title` = ?") + params = append(params, obj.getTitleForDB()) + } + if obj.CategoryId.IsUpdated() { + updatedFields = append(updatedFields, "`category_id` = ?") + params = append(params, obj.getCategoryIdForDB()) + } + if obj.IsPinned.IsUpdated() { + updatedFields = append(updatedFields, "`is_pinned` = ?") + params = append(params, obj.getIsPinnedForDB()) + } + if obj.IsVip.IsUpdated() { + updatedFields = append(updatedFields, "`is_vip` = ?") + params = append(params, obj.getIsVipForDB()) + } + if obj.Country.IsUpdated() { + updatedFields = append(updatedFields, "`country` = ?") + params = append(params, obj.getCountryForDB()) + } + if obj.CreatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, obj.getCreatedAtForDB()) + } + if obj.UpdatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, obj.getUpdatedAtForDB()) + } + if obj.Count_.IsUpdated() { + updatedFields = append(updatedFields, "`count` = ?") + params = append(params, obj.getCountForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `blogs` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Blog struct with given fields in `blogs` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *UserId: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`user_id` = ?") + params = append(params, c.getUserIdForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Slug: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`slug` = ?") + params = append(params, c.getSlugForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Title: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`title` = ?") + params = append(params, c.getTitleForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CategoryId: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`category_id` = ?") + params = append(params, c.getCategoryIdForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsPinned: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_pinned` = ?") + params = append(params, c.getIsPinnedForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsVip: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_vip` = ?") + params = append(params, c.getIsVipForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Country: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`country` = ?") + params = append(params, c.getCountryForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, c.getCreatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, c.getUpdatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Count_: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`count` = ?") + params = append(params, c.getCountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `blogs` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/gifts/gifts_tx.go b/golalib/testdata/gifts/gifts_tx.go new file mode 100644 index 0000000..1356636 --- /dev/null +++ b/golalib/testdata/gifts/gifts_tx.go @@ -0,0 +1,241 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package gifts + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Gift struct to `gifts` table with transaction +func (c *Gift) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Gift struct in `gifts` table with transaction +func (obj *Gift) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.IsFree.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, obj.getIsFreeForDB()) + } + if obj.GiftCount.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, obj.getGiftCountForDB()) + } + if obj.GiftType.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, obj.getGiftTypeForDB()) + } + if obj.CreateTime.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, obj.getCreateTimeForDB()) + } + if obj.Discount.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, obj.getDiscountForDB()) + } + if obj.Price.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, obj.getPriceForDB()) + } + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.Manifest.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, obj.getManifestForDB()) + } + if obj.Description.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, obj.getDescriptionForDB()) + } + if obj.UpdateTime.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, obj.getUpdateTimeForDB()) + } + if obj.Branches.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, obj.getBranchesForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Gift struct with given fields in `gifts` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsFree: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, c.getIsFreeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftCount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, c.getGiftCountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, c.getGiftTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, c.getCreateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Discount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, c.getDiscountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Price: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, c.getPriceForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Manifest: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, c.getManifestForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Description: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, c.getDescriptionForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, c.getUpdateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Branches: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, c.getBranchesForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/gifts_nn/gifts_nn_tx.go b/golalib/testdata/gifts_nn/gifts_nn_tx.go new file mode 100644 index 0000000..46ec98a --- /dev/null +++ b/golalib/testdata/gifts_nn/gifts_nn_tx.go @@ -0,0 +1,241 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package gifts_nn + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts GiftsNn struct to `gifts_nn` table with transaction +func (c *GiftsNn) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates GiftsNn struct in `gifts_nn` table with transaction +func (obj *GiftsNn) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.IsFree.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, obj.getIsFreeForDB()) + } + if obj.GiftCount.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, obj.getGiftCountForDB()) + } + if obj.GiftType.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, obj.getGiftTypeForDB()) + } + if obj.CreateTime.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, obj.getCreateTimeForDB()) + } + if obj.Discount.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, obj.getDiscountForDB()) + } + if obj.Price.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, obj.getPriceForDB()) + } + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.Manifest.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, obj.getManifestForDB()) + } + if obj.Description.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, obj.getDescriptionForDB()) + } + if obj.UpdateTime.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, obj.getUpdateTimeForDB()) + } + if obj.Branches.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, obj.getBranchesForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_nn` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates GiftsNn struct with given fields in `gifts_nn` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsFree: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, c.getIsFreeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftCount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, c.getGiftCountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, c.getGiftTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, c.getCreateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Discount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, c.getDiscountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Price: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, c.getPriceForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Manifest: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, c.getManifestForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Description: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, c.getDescriptionForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, c.getUpdateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Branches: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, c.getBranchesForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_nn` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/gifts_nn_with_default.sql b/golalib/testdata/gifts_nn_with_default.sql index 940aaae..f8226a7 100644 --- a/golalib/testdata/gifts_nn_with_default.sql +++ b/golalib/testdata/gifts_nn_with_default.sql @@ -10,7 +10,7 @@ CREATE TABLE `gifts_nn_with_default` ( `remark` varchar(128) NOT NULL default 'hope you like it', `manifest` varbinary(255) NOT NULL default 'manifest data', `description` text NOT NULL, - `update_time` timestamp NOT NULL default '2023-01-19 03:14:07.999999', + `update_time` timestamp NOT NULL default '2023-01-19 03:14:07.0', `update_time2` timestamp NOT NULL default CURRENT_TIMESTAMP, `branches` set('orchard','vivo','sentosa','changi') NOT NULL default 'sentosa,changi', PRIMARY KEY (`id`) diff --git a/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default.go b/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default.go index ce51b11..2a4b8ff 100644 --- a/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default.go +++ b/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default.go @@ -945,7 +945,7 @@ func New() *GiftsNnWithDefault { Remark{val: "hope you like it"}, Manifest{val: []byte("manifest data")}, Description{}, - UpdateTime{val: coredb.MustParseTime("2023-01-19 03:14:07.999999")}, + UpdateTime{val: coredb.MustParseTime("2023-01-19 03:14:07.0")}, UpdateTime2{val: time.Now()}, Branches{val: "sentosa,changi"}, } @@ -966,7 +966,7 @@ func NewWithPK(val uint) *GiftsNnWithDefault { Remark{val: "hope you like it"}, Manifest{val: []byte("manifest data")}, Description{}, - UpdateTime{val: coredb.MustParseTime("2023-01-19 03:14:07.999999")}, + UpdateTime{val: coredb.MustParseTime("2023-01-19 03:14:07.0")}, UpdateTime2{val: time.Now()}, Branches{val: "sentosa,changi"}, } diff --git a/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default_tx.go b/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default_tx.go new file mode 100644 index 0000000..bff7a57 --- /dev/null +++ b/golalib/testdata/gifts_nn_with_default/gifts_nn_with_default_tx.go @@ -0,0 +1,251 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package gifts_nn_with_default + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts GiftsNnWithDefault struct to `gifts_nn_with_default` table with transaction +func (c *GiftsNnWithDefault) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getUpdateTime2ForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getUpdateTime2ForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates GiftsNnWithDefault struct in `gifts_nn_with_default` table with transaction +func (obj *GiftsNnWithDefault) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.IsFree.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, obj.getIsFreeForDB()) + } + if obj.GiftCount.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, obj.getGiftCountForDB()) + } + if obj.GiftType.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, obj.getGiftTypeForDB()) + } + if obj.CreateTime.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, obj.getCreateTimeForDB()) + } + if obj.Discount.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, obj.getDiscountForDB()) + } + if obj.Price.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, obj.getPriceForDB()) + } + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.Manifest.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, obj.getManifestForDB()) + } + if obj.Description.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, obj.getDescriptionForDB()) + } + if obj.UpdateTime.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, obj.getUpdateTimeForDB()) + } + if obj.UpdateTime2.IsUpdated() { + updatedFields = append(updatedFields, "`update_time2` = ?") + params = append(params, obj.getUpdateTime2ForDB()) + } + if obj.Branches.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, obj.getBranchesForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_nn_with_default` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates GiftsNnWithDefault struct with given fields in `gifts_nn_with_default` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsFree: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, c.getIsFreeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftCount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, c.getGiftCountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, c.getGiftTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, c.getCreateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Discount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, c.getDiscountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Price: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, c.getPriceForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Manifest: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, c.getManifestForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Description: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, c.getDescriptionForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, c.getUpdateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime2: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time2` = ?") + params = append(params, c.getUpdateTime2ForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Branches: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, c.getBranchesForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_nn_with_default` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/gifts_with_default.sql b/golalib/testdata/gifts_with_default.sql index b26d287..2da0062 100644 --- a/golalib/testdata/gifts_with_default.sql +++ b/golalib/testdata/gifts_with_default.sql @@ -10,7 +10,7 @@ CREATE TABLE `gifts_with_default` ( `remark` varchar(128) default 'hope you like it', `manifest` varbinary(255) default 'manifest data', `description` text, - `update_time` timestamp default '2023-01-19 03:14:07.999999', + `update_time` timestamp default '2023-01-19 03:14:07.0', `update_time2` timestamp default CURRENT_TIMESTAMP, `branches` set('orchard','vivo','sentosa','changi') default 'sentosa,changi', PRIMARY KEY (`id`) diff --git a/golalib/testdata/gifts_with_default/gifts_with_default.go b/golalib/testdata/gifts_with_default/gifts_with_default.go index 073e40b..961cac2 100644 --- a/golalib/testdata/gifts_with_default/gifts_with_default.go +++ b/golalib/testdata/gifts_with_default/gifts_with_default.go @@ -970,7 +970,7 @@ func New() *GiftsWithDefault { Remark{val: goption.Some[string]("hope you like it")}, Manifest{val: goption.Some[[]byte]([]byte("manifest data"))}, Description{}, - UpdateTime{val: goption.Some[time.Time](coredb.MustParseTime("2023-01-19 03:14:07.999999"))}, + UpdateTime{val: goption.Some[time.Time](coredb.MustParseTime("2023-01-19 03:14:07.0"))}, UpdateTime2{val: goption.Some[time.Time](time.Now())}, Branches{val: goption.Some[string]("sentosa,changi")}, } @@ -991,7 +991,7 @@ func NewWithPK(val uint) *GiftsWithDefault { Remark{val: goption.Some[string]("hope you like it")}, Manifest{val: goption.Some[[]byte]([]byte("manifest data"))}, Description{}, - UpdateTime{val: goption.Some[time.Time](coredb.MustParseTime("2023-01-19 03:14:07.999999"))}, + UpdateTime{val: goption.Some[time.Time](coredb.MustParseTime("2023-01-19 03:14:07.0"))}, UpdateTime2{val: goption.Some[time.Time](time.Now())}, Branches{val: goption.Some[string]("sentosa,changi")}, } diff --git a/golalib/testdata/gifts_with_default/gifts_with_default_tx.go b/golalib/testdata/gifts_with_default/gifts_with_default_tx.go new file mode 100644 index 0000000..acc844f --- /dev/null +++ b/golalib/testdata/gifts_with_default/gifts_with_default_tx.go @@ -0,0 +1,251 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package gifts_with_default + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts GiftsWithDefault struct to `gifts_with_default` table with transaction +func (c *GiftsWithDefault) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getUpdateTime2ForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getIsFreeForDB(), c.getGiftCountForDB(), c.getGiftTypeForDB(), c.getCreateTimeForDB(), c.getDiscountForDB(), c.getPriceForDB(), c.getRemarkForDB(), c.getManifestForDB(), c.getDescriptionForDB(), c.getUpdateTimeForDB(), c.getUpdateTime2ForDB(), c.getBranchesForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates GiftsWithDefault struct in `gifts_with_default` table with transaction +func (obj *GiftsWithDefault) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.IsFree.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, obj.getIsFreeForDB()) + } + if obj.GiftCount.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, obj.getGiftCountForDB()) + } + if obj.GiftType.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, obj.getGiftTypeForDB()) + } + if obj.CreateTime.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, obj.getCreateTimeForDB()) + } + if obj.Discount.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, obj.getDiscountForDB()) + } + if obj.Price.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, obj.getPriceForDB()) + } + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.Manifest.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, obj.getManifestForDB()) + } + if obj.Description.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, obj.getDescriptionForDB()) + } + if obj.UpdateTime.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, obj.getUpdateTimeForDB()) + } + if obj.UpdateTime2.IsUpdated() { + updatedFields = append(updatedFields, "`update_time2` = ?") + params = append(params, obj.getUpdateTime2ForDB()) + } + if obj.Branches.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, obj.getBranchesForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_with_default` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates GiftsWithDefault struct with given fields in `gifts_with_default` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsFree: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_free` = ?") + params = append(params, c.getIsFreeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftCount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_count` = ?") + params = append(params, c.getGiftCountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *GiftType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`gift_type` = ?") + params = append(params, c.getGiftTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`create_time` = ?") + params = append(params, c.getCreateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Discount: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`discount` = ?") + params = append(params, c.getDiscountForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Price: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`price` = ?") + params = append(params, c.getPriceForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Manifest: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, c.getManifestForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Description: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`description` = ?") + params = append(params, c.getDescriptionForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time` = ?") + params = append(params, c.getUpdateTimeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdateTime2: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`update_time2` = ?") + params = append(params, c.getUpdateTime2ForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Branches: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`branches` = ?") + params = append(params, c.getBranchesForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `gifts_with_default` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/profile/profile_tx.go b/golalib/testdata/profile/profile_tx.go new file mode 100644 index 0000000..91b4c78 --- /dev/null +++ b/golalib/testdata/profile/profile_tx.go @@ -0,0 +1,128 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package profile + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Profile struct to `profile` table with transaction +func (c *Profile) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getUserIdForDB(), c.getLevelForDB(), c.getNickNameForDB()) + if err != nil { + return err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Profile struct in `profile` table with transaction +func (obj *Profile) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Level.IsUpdated() { + updatedFields = append(updatedFields, "`level` = ?") + params = append(params, obj.getLevelForDB()) + } + if obj.NickName.IsUpdated() { + updatedFields = append(updatedFields, "`nick_name` = ?") + params = append(params, obj.getNickNameForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `profile` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ?" + params = append(params, obj.GetUserId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Profile struct with given fields in `profile` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Level: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`level` = ?") + params = append(params, c.getLevelForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *NickName: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`nick_name` = ?") + params = append(params, c.getNickNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `profile` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ?" + params = append(params, obj.GetUserId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/room/room_tx.go b/golalib/testdata/room/room_tx.go new file mode 100644 index 0000000..e71f366 --- /dev/null +++ b/golalib/testdata/room/room_tx.go @@ -0,0 +1,161 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package room + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Room struct to `room` table with transaction +func (c *Room) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getGroupForDB(), c.getLangForDB(), c.getPriorityForDB(), c.getDeletedForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getGroupForDB(), c.getLangForDB(), c.getPriorityForDB(), c.getDeletedForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Room struct in `room` table with transaction +func (obj *Room) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Group.IsUpdated() { + updatedFields = append(updatedFields, "`group` = ?") + params = append(params, obj.getGroupForDB()) + } + if obj.Lang.IsUpdated() { + updatedFields = append(updatedFields, "`lang` = ?") + params = append(params, obj.getLangForDB()) + } + if obj.Priority.IsUpdated() { + updatedFields = append(updatedFields, "`priority` = ?") + params = append(params, obj.getPriorityForDB()) + } + if obj.Deleted.IsUpdated() { + updatedFields = append(updatedFields, "`deleted` = ?") + params = append(params, obj.getDeletedForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `room` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Room struct with given fields in `room` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Group: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`group` = ?") + params = append(params, c.getGroupForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Lang: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`lang` = ?") + params = append(params, c.getLangForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Priority: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`priority` = ?") + params = append(params, c.getPriorityForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Deleted: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`deleted` = ?") + params = append(params, c.getDeletedForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `room` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/song_user_favourites/song_user_favourites_tx.go b/golalib/testdata/song_user_favourites/song_user_favourites_tx.go new file mode 100644 index 0000000..1608fb8 --- /dev/null +++ b/golalib/testdata/song_user_favourites/song_user_favourites_tx.go @@ -0,0 +1,148 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package song_user_favourites + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts SongUserFavourite struct to `song_user_favourites` table with transaction +func (c *SongUserFavourite) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getUserIdForDB(), c.getSongIdForDB(), c.getRemarkForDB(), c.getIsFavouriteForDB(), c.getCreatedAtForDB(), c.getUpdatedAtForDB()) + if err != nil { + return err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates SongUserFavourite struct in `song_user_favourites` table with transaction +func (obj *SongUserFavourite) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.IsFavourite.IsUpdated() { + updatedFields = append(updatedFields, "`is_favourite` = ?") + params = append(params, obj.getIsFavouriteForDB()) + } + if obj.CreatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, obj.getCreatedAtForDB()) + } + if obj.UpdatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, obj.getUpdatedAtForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `song_user_favourites` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `song_id` = ?" + params = append(params, obj.GetUserId(), obj.GetSongId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates SongUserFavourite struct with given fields in `song_user_favourites` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *IsFavourite: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`is_favourite` = ?") + params = append(params, c.getIsFavouriteForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, c.getCreatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, c.getUpdatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `song_user_favourites` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `song_id` = ?" + params = append(params, obj.GetUserId(), obj.GetSongId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/songs/songs_tx.go b/golalib/testdata/songs/songs_tx.go new file mode 100644 index 0000000..4b3fc7c --- /dev/null +++ b/golalib/testdata/songs/songs_tx.go @@ -0,0 +1,181 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package songs + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Song struct to `songs` table with transaction +func (c *Song) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getTitleForDB(), c.getRankForDB(), c.getTypeForDB(), c.getHashForDB(), c.getRemarkForDB(), c.getManifestForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getTitleForDB(), c.getRankForDB(), c.getTypeForDB(), c.getHashForDB(), c.getRemarkForDB(), c.getManifestForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = uint(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Song struct in `songs` table with transaction +func (obj *Song) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Title.IsUpdated() { + updatedFields = append(updatedFields, "`title` = ?") + params = append(params, obj.getTitleForDB()) + } + if obj.Rank.IsUpdated() { + updatedFields = append(updatedFields, "`rank` = ?") + params = append(params, obj.getRankForDB()) + } + if obj.Type.IsUpdated() { + updatedFields = append(updatedFields, "`type` = ?") + params = append(params, obj.getTypeForDB()) + } + if obj.Hash.IsUpdated() { + updatedFields = append(updatedFields, "`hash` = ?") + params = append(params, obj.getHashForDB()) + } + if obj.Remark.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, obj.getRemarkForDB()) + } + if obj.Manifest.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, obj.getManifestForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `songs` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Song struct with given fields in `songs` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Title: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`title` = ?") + params = append(params, c.getTitleForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Rank: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`rank` = ?") + params = append(params, c.getRankForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Type: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`type` = ?") + params = append(params, c.getTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Hash: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`hash` = ?") + params = append(params, c.getHashForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Remark: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`remark` = ?") + params = append(params, c.getRemarkForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Manifest: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`manifest` = ?") + params = append(params, c.getManifestForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `songs` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/users.sql b/golalib/testdata/users.sql index 8eeb55e..d07bef4 100644 --- a/golalib/testdata/users.sql +++ b/golalib/testdata/users.sql @@ -8,9 +8,9 @@ CREATE TABLE `users` ( `double_type` double NOT NULL DEFAULT 0.0 COMMENT 'double', `hobby` enum ('swimming', 'running', 'singing') NOT NULL DEFAULT 'swimming' COMMENT 'user hobby', `hobby_no_default` enum ('swimming', 'running', 'singing') NOT NULL COMMENT 'user hobby', - `sports` SET('SWIM', 'TENNIS', 'BASKETBALL', 'FOOTBALL', 'SQUASH', 'BADMINTON') NOT NULL DEFAULT "SWIM,FOOTBALL" COMMENT 'user sports', - `sports2` SET('SWIM', 'TENNIS', 'BASKETBALL', 'FOOTBALL', 'SQUASH', 'BADMINTON') NOT NULL DEFAULT "SWIM,FOOTBALL" COMMENT 'user sports', - `sports_no_default` SET('SWIM', 'TENNIS', 'BASKETBALL', 'FOOTBALL', 'SQUASH', 'BADMINTON') NOT NULL COMMENT 'user sports', + `sports` SET('swim', 'tennis', 'basketball', 'football', 'squash', 'badminton') NOT NULL DEFAULT "swim,football" COMMENT 'user sports', + `sports2` SET('swim', 'tennis', 'basketball', 'football', 'squash', 'badminton') NOT NULL DEFAULT "swim,football" COMMENT 'user sports', + `sports_no_default` SET('swim', 'tennis', 'basketball', 'football', 'squash', 'badminton') NOT NULL COMMENT 'user sports', PRIMARY KEY (`id`), KEY `name` (`name`), UNIQUE KEY `email` (`email`) diff --git a/golalib/testdata/users/users_tx.go b/golalib/testdata/users/users_tx.go new file mode 100644 index 0000000..05dcc41 --- /dev/null +++ b/golalib/testdata/users/users_tx.go @@ -0,0 +1,231 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package users + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts User struct to `users` table with transaction +func (c *User) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getEmailForDB(), c.getCreatedAtForDB(), c.getUpdatedAtForDB(), c.getFloatTypeForDB(), c.getDoubleTypeForDB(), c.getHobbyForDB(), c.getHobbyNoDefaultForDB(), c.getSportsForDB(), c.getSports2ForDB(), c.getSportsNoDefaultForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getEmailForDB(), c.getCreatedAtForDB(), c.getUpdatedAtForDB(), c.getFloatTypeForDB(), c.getDoubleTypeForDB(), c.getHobbyForDB(), c.getHobbyNoDefaultForDB(), c.getSportsForDB(), c.getSports2ForDB(), c.getSportsNoDefaultForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = int(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates User struct in `users` table with transaction +func (obj *User) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.Email.IsUpdated() { + updatedFields = append(updatedFields, "`email` = ?") + params = append(params, obj.getEmailForDB()) + } + if obj.CreatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, obj.getCreatedAtForDB()) + } + if obj.UpdatedAt.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, obj.getUpdatedAtForDB()) + } + if obj.FloatType.IsUpdated() { + updatedFields = append(updatedFields, "`float_type` = ?") + params = append(params, obj.getFloatTypeForDB()) + } + if obj.DoubleType.IsUpdated() { + updatedFields = append(updatedFields, "`double_type` = ?") + params = append(params, obj.getDoubleTypeForDB()) + } + if obj.Hobby.IsUpdated() { + updatedFields = append(updatedFields, "`hobby` = ?") + params = append(params, obj.getHobbyForDB()) + } + if obj.HobbyNoDefault.IsUpdated() { + updatedFields = append(updatedFields, "`hobby_no_default` = ?") + params = append(params, obj.getHobbyNoDefaultForDB()) + } + if obj.Sports.IsUpdated() { + updatedFields = append(updatedFields, "`sports` = ?") + params = append(params, obj.getSportsForDB()) + } + if obj.Sports2.IsUpdated() { + updatedFields = append(updatedFields, "`sports2` = ?") + params = append(params, obj.getSports2ForDB()) + } + if obj.SportsNoDefault.IsUpdated() { + updatedFields = append(updatedFields, "`sports_no_default` = ?") + params = append(params, obj.getSportsNoDefaultForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `users` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates User struct with given fields in `users` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Email: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`email` = ?") + params = append(params, c.getEmailForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *CreatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`created_at` = ?") + params = append(params, c.getCreatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *UpdatedAt: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`updated_at` = ?") + params = append(params, c.getUpdatedAtForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *FloatType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`float_type` = ?") + params = append(params, c.getFloatTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *DoubleType: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`double_type` = ?") + params = append(params, c.getDoubleTypeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Hobby: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`hobby` = ?") + params = append(params, c.getHobbyForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *HobbyNoDefault: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`hobby_no_default` = ?") + params = append(params, c.getHobbyNoDefaultForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Sports: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`sports` = ?") + params = append(params, c.getSportsForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Sports2: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`sports2` = ?") + params = append(params, c.getSports2ForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *SportsNoDefault: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`sports_no_default` = ?") + params = append(params, c.getSportsNoDefaultForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `users` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/wallet/wallet_tx.go b/golalib/testdata/wallet/wallet_tx.go new file mode 100644 index 0000000..894031c --- /dev/null +++ b/golalib/testdata/wallet/wallet_tx.go @@ -0,0 +1,128 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package wallet + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Wallet struct to `wallet` table with transaction +func (c *Wallet) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getUserIdForDB(), c.getWalletTypeForDB(), c.getWalletNameForDB(), c.getMoneyForDB()) + if err != nil { + return err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Wallet struct in `wallet` table with transaction +func (obj *Wallet) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.WalletName.IsUpdated() { + updatedFields = append(updatedFields, "`wallet_name` = ?") + params = append(params, obj.getWalletNameForDB()) + } + if obj.Money.IsUpdated() { + updatedFields = append(updatedFields, "`money` = ?") + params = append(params, obj.getMoneyForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `wallet` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `wallet_type` = ?" + params = append(params, obj.GetUserId(), obj.GetWalletType()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Wallet struct with given fields in `wallet` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *WalletName: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`wallet_name` = ?") + params = append(params, c.getWalletNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Money: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`money` = ?") + params = append(params, c.getMoneyForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `wallet` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `user_id` = ? and `wallet_type` = ?" + params = append(params, obj.GetUserId(), obj.GetWalletType()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/golalib/testdata/worker/worker_tx.go b/golalib/testdata/worker/worker_tx.go new file mode 100644 index 0000000..3dedc43 --- /dev/null +++ b/golalib/testdata/worker/worker_tx.go @@ -0,0 +1,141 @@ +// Code generated by gola 0.1.1; DO NOT EDIT. + +package worker + +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" +) + +// InsertTx inserts Worker struct to `worker` table with transaction +func (c *Worker) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + if c.Id.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, c.getIdForDB(), c.getNameForDB(), c.getAgeForDB()) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, c.getNameForDB(), c.getAgeForDB()) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.Id.val = int(id) + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates Worker struct in `worker` table with transaction +func (obj *Worker) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + if obj.Name.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, obj.getNameForDB()) + } + if obj.Age.IsUpdated() { + updatedFields = append(updatedFields, "`age` = ?") + params = append(params, obj.getAgeForDB()) + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `worker` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates Worker struct with given fields in `worker` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + case *Name: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`name` = ?") + params = append(params, c.getNameForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + case *Age: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`age` = ?") + params = append(params, c.getAgeForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `worker` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE `id` = ?" + params = append(params, obj.GetId()) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/ormtpl/00_struct_tx.gogo b/ormtpl/00_struct_tx.gogo new file mode 100644 index 0000000..04be3aa --- /dev/null +++ b/ormtpl/00_struct_tx.gogo @@ -0,0 +1,150 @@ +// Code generated by gola {{.GetVersion}}; DO NOT EDIT. + +package {{.Package}} +{{$table := .}} +import ( + "context" + "database/sql" + "reflect" + "strings" + + "github.com/olachat/gola/v2/coredb/txengine" + "github.com/olachat/gola/v2/coredb" +) + +// InsertTx inserts {{.ClassName}} struct to `{{.Name}}` table with transaction +func (c *{{.ClassName}}) InsertTx(ctx context.Context, tx *sql.Tx) error { + var result sql.Result + var err error + + {{- if .IsPKAutoGenerated }} + if c.{{.GetPrimaryKey}}.isAssigned { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithPK, {{- range $i, $c := .Columns }} + {{- if $i}}, {{end}}c.get{{$c.GoName}}ForDB() + {{- end }}) + if err != nil { + return err + } + } else { + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, {{- range $i, $c := .GetNonAutoIncrementColumns }} + {{- if $i}}, {{end}}c.get{{$c.GoName}}ForDB() + {{- end }}) + if err != nil { + return err + } + + id, err := result.LastInsertId() + if err != nil { + return err + } + c.{{.GetPrimaryKey}}.val = {{.GetPrimaryKeyType}}(id) + } + {{else}} + result, err = txengine.WithTx(tx).Exec(ctx, insertWithoutPK, {{- range $i, $c := .GetNonAutoIncrementColumns }} + {{- if $i}}, {{end}}c.get{{$c.GoName}}ForDB() + {{- end }}) + if err != nil { + return err + } + {{- end}} + + affectedRows, err := result.RowsAffected() + if err != nil { + return err + } + if affectedRows == 0 { + return coredb.ErrAvoidInsert + } + + c.resetUpdated() + return nil +} + +// UpdateTx updates {{.ClassName}} struct in `{{.Name}}` table with transaction +func (obj *{{.ClassName}}) UpdateTx(ctx context.Context, tx *sql.Tx) (bool, error) { + var updatedFields []string + var params []any + + {{- range $i, $c := .GetNonPKColumns }} + if obj.{{ $c.GoTypeName }}.IsUpdated() { + updatedFields = append(updatedFields, "`{{ $c.Name }}` = ?") + params = append(params, obj.get{{$c.GoName}}ForDB()) + } + {{- end }} + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `{{.Name}}` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE {{.GetPrimaryKeySQL}}" + params = append(params, {{.GetPrimaryKeyParams}}) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + obj.resetUpdated() + return true, nil +} + +// UpdateTx updates {{.ClassName}} struct with given fields in `{{.Name}}` table with transaction +func UpdateTx(ctx context.Context, tx *sql.Tx, obj withPK) (bool, error) { + var updatedFields []string + var params []any + var resetFuncs []func() + + val := reflect.ValueOf(obj).Elem() + updatedFields = make([]string, 0, val.NumField()) + params = make([]any, 0, val.NumField()) + + for i := 0; i < val.NumField(); i++ { + col := val.Field(i).Addr().Interface() + + switch c := col.(type) { + {{- range $i, $c := .GetNonPKColumns }} + case *{{.GoTypeName}}: + if c.IsUpdated() { + updatedFields = append(updatedFields, "`{{ $c.Name }}` = ?") + params = append(params, c.get{{$c.GoName}}ForDB()) + resetFuncs = append(resetFuncs, c.resetUpdated) + } + {{- end }} + } + } + + if len(updatedFields) == 0 { + return false, nil + } + + sql := "UPDATE `{{.Name}}` SET " + sql = sql + strings.Join(updatedFields, ",") + " WHERE {{.GetPrimaryKeySQL}}" + params = append(params, {{.GetPrimaryKeyParams}}) + + result, err := txengine.WithTx(tx).Exec(ctx, sql, params...) + if err != nil { + return false, err + } + + affectedRows, err := result.RowsAffected() + if err != nil { + return false, err + } + if affectedRows == 0 { + return false, coredb.ErrAvoidUpdate + } + + for _, f := range resetFuncs { + f() + } + return true, nil +} diff --git a/tests/blog_test.go b/tests/blog_test.go index 31e2dd8..f7a79f7 100644 --- a/tests/blog_test.go +++ b/tests/blog_test.go @@ -1,8 +1,14 @@ package tests import ( + "context" + "database/sql" + "errors" + "fmt" "testing" + "github.com/olachat/gola/v2/coredb" + "github.com/olachat/gola/v2/coredb/txengine" "github.com/olachat/gola/v2/golalib/testdata/blogs" ) @@ -39,6 +45,7 @@ func TestBlogMethods(t *testing.T) { blog = blogs.New() blog.SetTitle("bar") blog.SetCount(88) + blog.SetSlug("slug") e = blog.Insert() if e != nil { t.Error(e) @@ -84,6 +91,128 @@ func TestBlogFind(t *testing.T) { } } +func TestBlogTx(t *testing.T) { + ctx := context.Background() + tx, err := coredb.BeginTx(ctx, blogs.DBName, &coredb.DefaultTxOpts) + if err != nil { + t.Fatalf("fail to start tx: %v", err) + } + err = txengine.StartTx(ctx, tx, func(ctx context.Context, sqlTx *sql.Tx) error { + blogRec, err := txengine.WithTypedTx[blogs.Blog](sqlTx).FindOne(ctx, blogs.TableName, coredb.NewWhere("where title = ?", "bar")) + if err != nil { + return err + } + if blogRec.GetId() != 3 { + t.Error("Find blog with title bar failed") + } + blogRec.SetCountry("GuaGua") + updateOk, err := blogRec.UpdateTx(ctx, sqlTx) + if err != nil { + return err + } + if !updateOk { + t.Error("fail to update blog in tx") + } + c, err := txengine.WithTx(sqlTx).QueryInt(ctx, "select count(*) from blogs where country = ?", "GuaGua") + if err != nil { + return fmt.Errorf("QueryInt failed: %w", err) + } + if c != 1 { + t.Error("expect count to be 1") + } + newBlog := blogs.New() + newBlog.SetCountry("GuaGua") + newBlog.SetSlug("oldSlug") + err = newBlog.InsertTx(ctx, sqlTx) + if err != nil { + return fmt.Errorf("fail to insert with Tx") + } + newBlog.SetSlug("slugadded123") + _, err = newBlog.UpdateTx(ctx, sqlTx) + if err != nil { + return fmt.Errorf("update failed: %w", err) + } + return nil + }) + if err != nil { + t.Fatal("error encountered", err) + } + obj := blogs.FindOneFromMaster("where title = ?", "bar") + if obj.GetId() != 3 { + t.Error("Find blog with title bar failed") + } + if obj.GetCountry() != "GuaGua" { + t.Error("blog not updated") + } + recs, err := blogs.FindCtx(ctx, "where country=? order by id desc", "GuaGua") + if err != nil { + t.Error(err) + } + if len(recs) != 2 { + t.Error("insertTx must have failed") + } + if recs[0].GetSlug() != "slugadded123" { + t.Error("wrong slug gotten") + } + + // start a new transaction + tx, err = coredb.BeginTx(ctx, blogs.DBName, &coredb.DefaultTxOpts) + if err != nil { + t.Fatalf("fail to start tx: %v", err) + } + err = txengine.StartTx(ctx, tx, func(ctx context.Context, sqlTx *sql.Tx) error { + blogRec, err := txengine.WithTypedTx[blogs.Blog](sqlTx).FindOne(ctx, blogs.TableName, coredb.NewWhere("where title = ?", "bar")) + if err != nil { + return err + } + if blogRec.GetId() != 3 { + t.Error("Find blog with title bar failed") + } + blogRec.SetCountry("PuaPua") + updateOk, err := blogRec.UpdateTx(ctx, sqlTx) + if err != nil { + return err + } + if !updateOk { + t.Error("fail to update blog in tx") + } + return errors.New("rollback") + }) + if err == nil { + t.Fatal("should get rollback error but err is nil") + } + // currently there is no way to test rollback using dolt in memory DB as transaction is not supported + + // start a new transaction + tx, err = coredb.BeginTx(ctx, blogs.DBName, &coredb.DefaultTxOpts) + if err != nil { + t.Fatalf("fail to start tx: %v", err) + } + err = txengine.StartTx(ctx, tx, func(ctx context.Context, sqlTx *sql.Tx) error { + blogRecs, err := txengine.WithTypedTx[struct { + blogs.Id + }](sqlTx).Find(ctx, blogs.TableName, coredb.NewWhere("where slug = ?", "slugadded123")) + if err != nil { + return err + } + if len(blogRecs) != 1 { + t.Errorf("expected to have 1 blog") + return errors.New("expected to have 1 blog") + } + id := blogRecs[0].GetId() + _, err = txengine.WithTx(sqlTx).Exec(ctx, "delete from blogs where id=?", id) + return err + }) + if err != nil { + t.Fatalf("tx delete failed") + } + r := blogs.FindOne("where slug = ?", "slugadded123") + if r != nil { + t.Error("r should already been deleted") + } + +} + func TestBlogFindT(t *testing.T) { obj := blogs.FindOneFieldsFromMaster[struct { blogs.Id diff --git a/tests/gifts_nn_test.go b/tests/gifts_nn_test.go index 7bf423f..5ee3bf3 100644 --- a/tests/gifts_nn_test.go +++ b/tests/gifts_nn_test.go @@ -145,7 +145,7 @@ func TestGiftNotNullInsertRetrieveUpdate(t *testing.T) { gOut.SetName("gift 2") gOut.SetPrice(65.555) gOut.SetRemark("remark 2") - now2 := time.Now().UTC().Truncate(time.Microsecond) + now2 := time.Now().UTC().Truncate(time.Second) gOut.SetUpdateTime(now2) ok, err := gOut.Update() if err != nil { @@ -198,7 +198,7 @@ func TestGiftNotNullInsertRetrieveUpdate(t *testing.T) { if g22.GetRemark() != "remark 2" { t.Error("wrong remark") } - if g22.GetUpdateTime() != now2 { - t.Error("wrong update time") + if !g22.GetUpdateTime().Equal(now2) { + t.Errorf("wrong update time. expected %s, gotten %s", now2, g22.GetUpdateTime()) } } diff --git a/tests/gifts_nn_with_default_test.go b/tests/gifts_nn_with_default_test.go index 6ca3cd4..66aa0f6 100644 --- a/tests/gifts_nn_with_default_test.go +++ b/tests/gifts_nn_with_default_test.go @@ -69,12 +69,12 @@ func assertDefaultGiftNnWithDefault(t *testing.T, gift *gifts_nn_with_default.Gi t.Error("wrong remark") } - ti, err := time.Parse("2006-01-02 15:04:05.999999", "2023-01-19 03:14:07.999999") + ti, err := time.Parse("2006-01-02 15:04:05.0", "2023-01-19 03:14:07.0") if err != nil { panic(err) } if !gift.GetUpdateTime().Equal(ti) { - t.Error("wrong update time") + t.Error("wrong update time", ti, gift.GetUpdateTime()) } fmt.Println(gift.GetUpdateTime2()) } @@ -118,7 +118,7 @@ func TestGiftNotNullWithDefaultInsertRetrieveUpdate(t *testing.T) { gift.SetName("gift 2") gift.SetPrice(65.555) gift.SetRemark("remark 2") - now2 := time.Now().UTC().Truncate(time.Microsecond) + now2 := time.Now().UTC().Truncate(time.Second) gift.SetUpdateTime(now2) ok, err := gift.Update() if err != nil { diff --git a/tests/gifts_test.go b/tests/gifts_test.go index 1a7b706..fc26464 100644 --- a/tests/gifts_test.go +++ b/tests/gifts_test.go @@ -182,7 +182,7 @@ func TestInsertRetrieveUpdate(t *testing.T) { g2.SetName(goption.Some("xmas gift")) g2.SetPrice(goption.Some(15.5)) g2.SetRemark(goption.Some("selling out soon")) - now := time.Now().UTC().Truncate(time.Microsecond) + now := time.Now().UTC().Truncate(time.Second) g2.SetUpdateTime(goption.Some(now)) err = g2.Insert() if err != nil { @@ -195,7 +195,7 @@ func TestInsertRetrieveUpdate(t *testing.T) { j2, _ := json.Marshal(g2) j2Out, _ := json.Marshal(g2out) if string(j2) != string(j2Out) { - t.Fatalf("gift fetched is not as expected") + t.Fatalf("gift fetched is not as expected %s %s", string(j2), string(j2Out)) } g2out.SetBranches(goption.Some([]gifts.GiftBranches{ @@ -212,7 +212,7 @@ func TestInsertRetrieveUpdate(t *testing.T) { g2out.SetName(goption.Some("gift 2")) g2out.SetPrice(goption.Some(65.555)) g2out.SetRemark(goption.Some("remark 2")) - now2 := time.Now().UTC().Truncate(time.Microsecond) + now2 := time.Now().UTC().Truncate(time.Second) g2out.SetUpdateTime(goption.Some(now2)) ok, err := g2out.Update() if err != nil { diff --git a/tests/gifts_with_default_test.go b/tests/gifts_with_default_test.go index 758fc9f..9bafb44 100644 --- a/tests/gifts_with_default_test.go +++ b/tests/gifts_with_default_test.go @@ -70,7 +70,7 @@ func assertDefaultGiftWithDefault(t *testing.T, gift *gifts_with_default.GiftsWi t.Error("wrong remark") } - ti, err := time.Parse("2006-01-02 15:04:05.999999", "2023-01-19 03:14:07.999999") + ti, err := time.Parse("2006-01-02 15:04:05.999999", "2023-01-19 03:14:07.0") if err != nil { panic(err) } @@ -175,7 +175,7 @@ func TestGiftWithDefaultInsertRetrieveUpdate(t *testing.T) { gOut.SetName(goption.Some("gift 2")) gOut.SetPrice(goption.Some(65.555)) gOut.SetRemark(goption.Some("remark 2")) - now2 := time.Now().UTC().Truncate(time.Microsecond) + now2 := time.Now().UTC().Truncate(time.Second) gOut.SetUpdateTime(goption.Some(now2)) ok, err := gOut.Update() if err != nil { diff --git a/tests/profile_test.go b/tests/profile_test.go index 826e6b4..a2dd484 100644 --- a/tests/profile_test.go +++ b/tests/profile_test.go @@ -29,8 +29,8 @@ func TestProfile(t *testing.T) { somehow coredb.ErrAvoidInsert is not returned should figure out why later */ - if err != nil { - t.Error(err) + if err == nil { + t.Error("duplicate unique key error should be returned but not") } p2 = profile.FetchByPK(8) diff --git a/tests/song_test.go b/tests/song_test.go index 50f63b2..e969203 100644 --- a/tests/song_test.go +++ b/tests/song_test.go @@ -329,11 +329,8 @@ func TestSongInsertWithPK(t *testing.T) { s.SetHash("hashhash") s.SetManifest([]byte("")) err = s.Insert() - if err != nil { - t.Error(err) - } - if s.GetId() != 1100+1+1 { - t.Error("Insert without pk after pk failed") + if err == nil { + t.Error("expected insert to fail with duplicate unique key error") } } diff --git a/tests/user_test.go b/tests/user_test.go index f4ed9c8..4f87757 100644 --- a/tests/user_test.go +++ b/tests/user_test.go @@ -70,13 +70,18 @@ func init() { db.Exec(string(query)) } + _, err = db.Exec("SET autocommit = 0") + if err != nil { + panic("fail to set autocommit mode") + } + // add data _, err = db.Exec(` insert into users (name, email, created_at, updated_at, float_type, double_type, hobby, hobby_no_default, sports_no_default, sports) values -("John Doe", "john@doe.com", NOW(), NOW(), 1.55555, 1.8729, 'running','swimming', ('SWIM,TENNIS'), ("TENNIS")), -("John Doe", "johnalt@doe.com", NOW(), NOW(), 2.5, 2.8239, 'swimming','running', ('BASKETBALL'), ("FOOTBALL")), -("Jane Doe", "jane@doe.com", NOW(), NOW(), 3.5, 334.8593, 'singing','swimming', ('SQUASH,BADMINTON'), ("SQUASH,TENNIS")), -("Evil Bob", "evilbob@gmail.com", NOW(), NOW(), 4.5, 42234.83, 'singing','running', 'tennis', 'BADMINTON,BASKETBALL') +("John Doe", "john@doe.com", NOW(), NOW(), 1.55555, 1.8729, 'running','swimming', ('swim,tennis'), ("tennis")), +("John Doe", "johnalt@doe.com", NOW(), NOW(), 2.5, 2.8239, 'swimming','running', ('basketball'), ("football")), +("Jane Doe", "jane@doe.com", NOW(), NOW(), 3.5, 334.8593, 'singing','swimming', ('squash,badminton'), ("squash,tennis")), +("Evil Bob", "evilbob@gmail.com", NOW(), NOW(), 4.5, 42234.83, 'singing','running', 'tennis', 'badminton,basketball') `) if err != nil { panic("insert failed " + err.Error())