diff --git a/.gitea/workflows/release-tag.yml b/.gitea/workflows/release-tag.yml index 3b788e76..3f26f1e0 100644 --- a/.gitea/workflows/release-tag.yml +++ b/.gitea/workflows/release-tag.yml @@ -5,6 +5,9 @@ on: tags: - '*' +env: + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path + jobs: release: runs-on: ubuntu-latest diff --git a/.gitea/workflows/test-cockroach.yml b/.gitea/workflows/test-cockroach.yml index cfcda89d..8ee7a8bf 100644 --- a/.gitea/workflows/test-cockroach.yml +++ b/.gitea/workflows/test-cockroach.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: test-cockroach: diff --git a/.gitea/workflows/test-mariadb.yml b/.gitea/workflows/test-mariadb.yml index dbc819db..7e64d2b8 100644 --- a/.gitea/workflows/test-mariadb.yml +++ b/.gitea/workflows/test-mariadb.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: lint: diff --git a/.gitea/workflows/test-mssql.yml b/.gitea/workflows/test-mssql.yml index 04b8031a..c5baf194 100644 --- a/.gitea/workflows/test-mssql.yml +++ b/.gitea/workflows/test-mssql.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: test-mssql: diff --git a/.gitea/workflows/test-mysql.yml b/.gitea/workflows/test-mysql.yml index e13354f0..0c31d0ea 100644 --- a/.gitea/workflows/test-mysql.yml +++ b/.gitea/workflows/test-mysql.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: test-mysql: diff --git a/.gitea/workflows/test-mysql8.yml b/.gitea/workflows/test-mysql8.yml index 7362065a..115ad803 100644 --- a/.gitea/workflows/test-mysql8.yml +++ b/.gitea/workflows/test-mysql8.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: lint: diff --git a/.gitea/workflows/test-postgres.yml b/.gitea/workflows/test-postgres.yml index d4abb2ad..721da794 100644 --- a/.gitea/workflows/test-postgres.yml +++ b/.gitea/workflows/test-postgres.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: lint: diff --git a/.gitea/workflows/test-sqlite.yml b/.gitea/workflows/test-sqlite.yml index 164acc10..3431b36b 100644 --- a/.gitea/workflows/test-sqlite.yml +++ b/.gitea/workflows/test-sqlite.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: test-sqlite: diff --git a/.gitea/workflows/test-tidb.yml b/.gitea/workflows/test-tidb.yml index ce898dcb..1495e7a6 100644 --- a/.gitea/workflows/test-tidb.yml +++ b/.gitea/workflows/test-tidb.yml @@ -9,6 +9,7 @@ env: GOPROXY: https://goproxy.io,direct GOPATH: /go_path GOCACHE: /go_cache + RUNNER_TOOL_CACHE: /toolcache # specify with your cache path jobs: test-tidb: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 27e6929b..9c70d0d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,8 +61,6 @@ TEST_PGSQL_HOST= TEST_PGSQL_SCHEMA= TEST_PGSQL_DBNAME= TEST_PGSQL_USERNAME= TEST TEST_TIDB_HOST= TEST_TIDB_DBNAME= TEST_TIDB_USERNAME= TEST_TIDB_PASSWORD= make test-tidb ``` -And if your branch is related with cache, you could also enable it via `TEST_CACHE_ENABLE=true`. - ### Patch review Help review existing open [pull requests](https://gitea.com/xorm/xorm/pulls) by commenting on the code or diff --git a/Makefile b/Makefile index 55183557..ff93f181 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,10 @@ GOFMT ?= gofmt -s TAGS ?= SED_INPLACE := sed -i -GO_DIRS := caches contexts integrations core dialects internal log migrate names schemas tags +GO_DIRS := contexts tests dialects internal log migrate names schemas tags GOFILES := $(wildcard *.go) GOFILES += $(shell find $(GO_DIRS) -name "*.go" -type f) -INTEGRATION_PACKAGES := xorm.io/xorm/tests +INTEGRATION_PACKAGES := xorm.io/xorm/v2/tests PACKAGES ?= $(filter-out $(INTEGRATION_PACKAGES),$(shell $(GO) list ./...)) TEST_COCKROACH_HOST ?= cockroach:26257 @@ -47,7 +47,6 @@ TEST_DAMENG_HOST ?= dameng:5236 TEST_DAMENG_USERNAME ?= SYSDBA TEST_DAMENG_PASSWORD ?= SYSDBA -TEST_CACHE_ENABLE ?= false TEST_QUOTE_POLICY ?= always .PHONY: all @@ -60,7 +59,7 @@ build: go-check $(GO_SOURCES) .PHONY: clean clean: $(GO) clean -i ./... - rm -rf *.sql *.log test.db cover.out cover.html *coverage.out coverage.all integrations/*.sql + rm -rf *.sql *.log test.db cover.out cover.html *coverage.out coverage.all tests/*.sql .PHONY: coverage coverage: @@ -137,145 +136,133 @@ test: go-check .PNONY: test-cockroach test-cockroach: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' \ -conn_str="postgres://$(TEST_COCKROACH_USERNAME):$(TEST_COCKROACH_PASSWORD)@$(TEST_COCKROACH_HOST)/$(TEST_COCKROACH_DBNAME)?sslmode=disable&experimental_serial_normalization=sql_sequence" \ - -ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).coverage.out -covermode=atomic -timeout=20m .PHONY: test-cockroach\#% test-cockroach\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' \ -conn_str="postgres://$(TEST_COCKROACH_USERNAME):$(TEST_COCKROACH_PASSWORD)@$(TEST_COCKROACH_HOST)/$(TEST_COCKROACH_DBNAME)?sslmode=disable&experimental_serial_normalization=sql_sequence" \ - -ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).coverage.out -covermode=atomic .PNONY: test-mssql test-mssql: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mssql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ - -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -coverprofile=mssql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PNONY: test-mssql\#% test-mssql\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mssql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \ -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ - -coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic - -.PNONY: test-mymysql -test-mymysql: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mymysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ - -conn_str="tcp:$(TEST_MYSQL_HOST)*$(TEST_MYSQL_DBNAME)/$(TEST_MYSQL_USERNAME)/$(TEST_MYSQL_PASSWORD)" \ - -coverprofile=mymysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m - -.PNONY: test-mymysql\#% -test-mymysql\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mymysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ - -conn_str="tcp:$(TEST_MYSQL_HOST)*$(TEST_MYSQL_DBNAME)/$(TEST_MYSQL_USERNAME)/$(TEST_MYSQL_PASSWORD)" \ - -coverprofile=mymysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -coverprofile=mssql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PNONY: test-mysql test-mysql: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)" \ - -coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -coverprofile=mysql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-mysql\#% test-mysql\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)" \ - -coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -coverprofile=mysql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PNONY: test-mysql-tls test-mysql-tls: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)&tls=skip-verify" \ - -coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -coverprofile=mysql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-mysql-tls\#% test-mysql-tls\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -quote=$(TEST_QUOTE_POLICY) \ -conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)&tls=skip-verify" \ - -coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -coverprofile=mysql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PNONY: test-postgres test-postgres: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' \ -conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-postgres\#% test-postgres\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' \ -conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PHONY: test-sqlite3 test-sqlite3: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-sqlite3-schema test-sqlite3-schema: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-sqlite3\#% test-sqlite3\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PNONY: test-pgx test-pgx: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=pgx -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=pgx -schema='$(TEST_PGSQL_SCHEMA)' \ -conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-pgx\#% test-pgx\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=pgx -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=pgx -schema='$(TEST_PGSQL_SCHEMA)' \ -conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-sqlite test-sqlite: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-sqlite-schema test-sqlite-schema: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + $(GO) test $(INTEGRATION_PACKAGES) -v -race -schema=xorm -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-sqlite\#% test-sqlite\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ + -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PNONY: test-tidb test-tidb: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -ignore_select_update=true \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=mysql -ignore_select_update=true \ -conn_str="$(TEST_TIDB_USERNAME):$(TEST_TIDB_PASSWORD)@tcp($(TEST_TIDB_HOST))/$(TEST_TIDB_DBNAME)" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-tidb\#% test-tidb\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -cache=$(TEST_CACHE_ENABLE) -ignore_select_update=true \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=mysql -ignore_select_update=true \ -conn_str="$(TEST_TIDB_USERNAME):$(TEST_TIDB_PASSWORD)@tcp($(TEST_TIDB_HOST))/$(TEST_TIDB_DBNAME)" \ - -quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic + -quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic .PNONY: test-dameng test-dameng: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=dm -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -db=dm -quote=$(TEST_QUOTE_POLICY) \ -conn_str="dm://$(TEST_DAMENG_USERNAME):$(TEST_DAMENG_PASSWORD)@$(TEST_DAMENG_HOST)" \ - -coverprofile=dameng.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -coverprofile=dameng.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: test-dameng\#% test-dameng\#%: go-check - $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=dm -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \ + $(GO) test $(INTEGRATION_PACKAGES) -v -race -run $* -db=dm -quote=$(TEST_QUOTE_POLICY) \ -conn_str="dm://$(TEST_DAMENG_USERNAME):$(TEST_DAMENG_PASSWORD)@$(TEST_DAMENG_HOST)" \ - -coverprofile=dameng.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m + -coverprofile=dameng.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m .PHONY: vet vet: diff --git a/README.md b/README.md index 1348f4f8..54cf1c5a 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ v1.0.0 has some break changes from v0.8.2. * Transaction Support * Both ORM and raw SQL operation Support * Sync database schema Support -* Query Cache speed up * Database Reverse support via [xorm.io/reverse](https://xorm.io/reverse) * Simple cascade loading support * Optimistic Locking support @@ -37,7 +36,6 @@ Drivers for Go's sql package which currently support database/sql includes: * [Mysql5.*](https://github.com/mysql/mysql-server/tree/5.7) / [Mysql8.*](https://github.com/mysql/mysql-server) / [Mariadb](https://github.com/MariaDB/server) / [Tidb](https://github.com/pingcap/tidb) - [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) - - [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach) - [github.com/lib/pq](https://github.com/lib/pq) @@ -57,13 +55,13 @@ Drivers for Go's sql package which currently support database/sql includes: ## Installation - go get xorm.io/xorm + go get xorm.io/xorm/v2 ## Documents * [Manual](http://xorm.io/docs) -* [GoDoc](http://pkg.go.dev/xorm.io/xorm) +* [GoDoc](http://pkg.go.dev/xorm.io/xorm/v2) ## Quick Start @@ -107,7 +105,7 @@ engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, sl Then all place where `engine` you can just use `engineGroup`. -* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`, `QueryInterface` returns `[]map[string]interface{}`. +* `Query` runs a SQL string, the returned results is `[]map[string][]byte`, `QueryString` returns `[]map[string]string`, `QueryInterface` returns `[]map[string]any`. ```Go results, err := engine.Query("select * from user") @@ -143,13 +141,13 @@ affected, err := engine.Insert(&user1, &users) // INSERT INTO struct1 () values () // INSERT INTO struct2 () values (),(),() -affected, err := engine.Table("user").Insert(map[string]interface{}{ +affected, err := engine.Table("user").Insert(map[string]any{ "name": "lunny", "age": 18, }) // INSERT INTO user (name, age) values (?,?) -affected, err := engine.Table("user").Insert([]map[string]interface{}{ +affected, err := engine.Table("user").Insert([]map[string]any{ { "name": "lunny", "age": 18, @@ -189,7 +187,7 @@ var valuesMap = make(map[string]string) has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap) // SELECT * FROM user WHERE id = ? -var valuesSlice = make([]interface{}, len(cols)) +var valuesSlice = make([]any, len(cols)) has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice) // SELECT col1, col2, col3 FROM user WHERE id = ? ``` @@ -246,13 +244,13 @@ err := engine.Table("user").Select("user.*, detail.*"). * `Iterate` and `Rows` query multiple records and record by record handle, there are two methods Iterate and Rows ```Go -err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error { +err := engine.Iterate(&User{Name:name}, func(idx int, bean any) error { user := bean.(*User) return nil }) // SELECT * FROM user -err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error { +err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean any) error { user := bean.(*User) return nil }) @@ -416,7 +414,7 @@ return session.Commit() * Or you can use `Transaction` to replace above codes. ```Go -res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) { +res, err := engine.Transaction(func(session *xorm.Session) (any, error) { user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} if _, err := session.Insert(&user1); err != nil { return nil, err @@ -490,20 +488,18 @@ You can find all the changelog [here](CHANGELOG.md) ## Cases -* [studygolang](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang) - -* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) - -* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) +* [Gitea](http://about.gitea.com) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) * [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) +* [studygolang](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang) + +* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) + * [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) * [Wego](http://github.com/go-tango/wego) -* [Docker.cn](https://docker.cn/) - * [Xorm Adapter](https://github.com/casbin/xorm-adapter) for [Casbin](https://github.com/casbin/casbin) - [github.com/casbin/xorm-adapter](https://github.com/casbin/xorm-adapter) * [Gorevel](http://gorevel.cn/) - [github.com/goofcc/gorevel](http://github.com/goofcc/gorevel) diff --git a/README_CN.md b/README_CN.md index aa466894..338b1d1f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -36,7 +36,6 @@ v1.0.0 相对于 v0.8.2 有以下不兼容的变更: * [Mysql5.*](https://github.com/mysql/mysql-server/tree/5.7) / [Mysql8.*](https://github.com/mysql/mysql-server) / [Mariadb](https://github.com/MariaDB/server) / [Tidb](https://github.com/pingcap/tidb) - [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) - - [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach) - [github.com/lib/pq](https://github.com/lib/pq) @@ -56,13 +55,13 @@ v1.0.0 相对于 v0.8.2 有以下不兼容的变更: ## 安装 - go get xorm.io/xorm + go get xorm.io/xorm/v2 ## 文档 * [操作指南](http://xorm.io/docs) -* [Godoc代码文档](http://pkg.go.dev/xorm.io/xorm) +* [Godoc代码文档](http://pkg.go.dev/xorm.io/xorm/v2) # 快速开始 @@ -104,7 +103,7 @@ engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, sl 所有使用 `engine` 都可以简单的用 `engineGroup` 来替换。 -* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 `[]map[string][]byte`。`QueryString` 返回 `[]map[string]string`, `QueryInterface` 返回 `[]map[string]interface{}`. +* `Query` 最原始的也支持SQL语句查询,返回的结果类型为 `[]map[string][]byte`。`QueryString` 返回 `[]map[string]string`, `QueryInterface` 返回 `[]map[string]any`. ```Go results, err := engine.Query("select * from user") @@ -140,13 +139,13 @@ affected, err := engine.Insert(&user1, &users) // INSERT INTO struct1 () values () // INSERT INTO struct2 () values (),(),() -affected, err := engine.Table("user").Insert(map[string]interface{}{ +affected, err := engine.Table("user").Insert(map[string]any{ "name": "lunny", "age": 18, }) // INSERT INTO user (name, age) values (?,?) -affected, err := engine.Table("user").Insert([]map[string]interface{}{ +affected, err := engine.Table("user").Insert([]map[string]any{ { "name": "lunny", "age": 18, @@ -186,7 +185,7 @@ var valuesMap = make(map[string]string) has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap) // SELECT * FROM user WHERE id = ? -var valuesSlice = make([]interface{}, len(cols)) +var valuesSlice = make([]any, len(cols)) has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice) // SELECT col1, col2, col3 FROM user WHERE id = ? ``` @@ -243,13 +242,13 @@ err := engine.Table("user").Select("user.*, detail.*"). * `Iterate` 和 `Rows` 根据条件遍历数据库,可以有两种方式: Iterate and Rows ```Go -err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error { +err := engine.Iterate(&User{Name:name}, func(idx int, bean any) error { user := bean.(*User) return nil }) // SELECT * FROM user -err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error { +err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean any) error { user := bean.(*User) return nil }) @@ -406,7 +405,7 @@ return session.Commit() * 事务的简写方法 ```Go -res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) { +res, err := engine.Transaction(func(session *xorm.Session) (any, error) { user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()} if _, err := session.Insert(&user1); err != nil { return nil, err diff --git a/caches/cache.go b/caches/cache.go deleted file mode 100644 index 7b80eb88..00000000 --- a/caches/cache.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2019 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "bytes" - "encoding/gob" - "errors" - "fmt" - "strings" - "time" - - "xorm.io/xorm/schemas" -) - -const ( - // CacheExpired is default cache expired time - CacheExpired = 60 * time.Minute - // CacheMaxMemory is not use now - CacheMaxMemory = 256 - // CacheGcInterval represents interval time to clear all expired nodes - CacheGcInterval = 10 * time.Minute - // CacheGcMaxRemoved represents max nodes removed when gc - CacheGcMaxRemoved = 20 -) - -// list all the errors -var ( - ErrCacheMiss = errors.New("xorm/cache: key not found") - ErrNotStored = errors.New("xorm/cache: not stored") - // ErrNotExist record does not exist error - ErrNotExist = errors.New("Record does not exist") -) - -// CacheStore is a interface to store cache -type CacheStore interface { - // key is primary key or composite primary key - // value is struct's pointer - // key format : -p--... - Put(key string, value interface{}) error - Get(key string) (interface{}, error) - Del(key string) error -} - -// Cacher is an interface to provide cache -// id format : u--... -type Cacher interface { - GetIds(tableName, sql string) interface{} - GetBean(tableName string, id string) interface{} - PutIds(tableName, sql string, ids interface{}) - PutBean(tableName string, id string, obj interface{}) - DelIds(tableName, sql string) - DelBean(tableName string, id string) - ClearIds(tableName string) - ClearBeans(tableName string) -} - -func encodeIds(ids []schemas.PK) (string, error) { - buf := new(bytes.Buffer) - enc := gob.NewEncoder(buf) - err := enc.Encode(ids) - - return buf.String(), err -} - -func decodeIds(s string) ([]schemas.PK, error) { - pks := make([]schemas.PK, 0) - - dec := gob.NewDecoder(strings.NewReader(s)) - err := dec.Decode(&pks) - - return pks, err -} - -// GetCacheSql returns cacher PKs via SQL -func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]schemas.PK, error) { - bytes := m.GetIds(tableName, GenSqlKey(sql, args)) - if bytes == nil { - return nil, errors.New("Not Exist") - } - return decodeIds(bytes.(string)) -} - -// PutCacheSql puts cacher SQL and PKs -func PutCacheSql(m Cacher, ids []schemas.PK, tableName, sql string, args interface{}) error { - bytes, err := encodeIds(ids) - if err != nil { - return err - } - m.PutIds(tableName, GenSqlKey(sql, args), bytes) - return nil -} - -// GenSqlKey generates cache key -func GenSqlKey(sql string, args interface{}) string { - return fmt.Sprintf("%v-%v", sql, args) -} diff --git a/caches/encode.go b/caches/encode.go deleted file mode 100644 index 8659668c..00000000 --- a/caches/encode.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2020 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "bytes" - "crypto/md5" - "encoding/gob" - "encoding/json" - "fmt" - "io" -) - -// Md5 return md5 hash string -func Md5(str string) string { - m := md5.New() - _, _ = io.WriteString(m, str) - return fmt.Sprintf("%x", m.Sum(nil)) -} - -// Encode Encode data -func Encode(data interface{}) ([]byte, error) { - // return JsonEncode(data) - return GobEncode(data) -} - -// Decode decode data -func Decode(data []byte, to interface{}) error { - // return JsonDecode(data, to) - return GobDecode(data, to) -} - -// GobEncode encode data with gob -func GobEncode(data interface{}) ([]byte, error) { - var buf bytes.Buffer - enc := gob.NewEncoder(&buf) - err := enc.Encode(&data) - if err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -// GobDecode decode data with gob -func GobDecode(data []byte, to interface{}) error { - buf := bytes.NewBuffer(data) - dec := gob.NewDecoder(buf) - return dec.Decode(to) -} - -// JsonEncode encode data with json -func JsonEncode(data interface{}) ([]byte, error) { - val, err := json.Marshal(data) - if err != nil { - return nil, err - } - return val, nil -} - -// JsonDecode decode data with json -func JsonDecode(data []byte, to interface{}) error { - return json.Unmarshal(data, to) -} diff --git a/caches/leveldb.go b/caches/leveldb.go deleted file mode 100644 index f2f71d84..00000000 --- a/caches/leveldb.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2020 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "log" - - "github.com/syndtr/goleveldb/leveldb" -) - -// LevelDBStore implements CacheStore provide local machine -type LevelDBStore struct { - store *leveldb.DB - Debug bool - v interface{} -} - -var _ CacheStore = &LevelDBStore{} - -// NewLevelDBStore creates a leveldb store -func NewLevelDBStore(dbfile string) (*LevelDBStore, error) { - db := &LevelDBStore{} - h, err := leveldb.OpenFile(dbfile, nil) - if err != nil { - return nil, err - } - db.store = h - return db, nil -} - -// Put implements CacheStore -func (s *LevelDBStore) Put(key string, value interface{}) error { - val, err := Encode(value) - if err != nil { - if s.Debug { - log.Println("[LevelDB]EncodeErr: ", err, "Key:", key) - } - return err - } - err = s.store.Put([]byte(key), val, nil) - if err != nil { - if s.Debug { - log.Println("[LevelDB]PutErr: ", err, "Key:", key) - } - return err - } - if s.Debug { - log.Println("[LevelDB]Put: ", key) - } - return err -} - -// Get implements CacheStore -func (s *LevelDBStore) Get(key string) (interface{}, error) { - data, err := s.store.Get([]byte(key), nil) - if err != nil { - if s.Debug { - log.Println("[LevelDB]GetErr: ", err, "Key:", key) - } - if err == leveldb.ErrNotFound { - return nil, ErrNotExist - } - return nil, err - } - - err = Decode(data, &s.v) - if err != nil { - if s.Debug { - log.Println("[LevelDB]DecodeErr: ", err, "Key:", key) - } - return nil, err - } - if s.Debug { - log.Println("[LevelDB]Get: ", key, s.v) - } - return s.v, err -} - -// Del implements CacheStore -func (s *LevelDBStore) Del(key string) error { - err := s.store.Delete([]byte(key), nil) - if err != nil { - if s.Debug { - log.Println("[LevelDB]DelErr: ", err, "Key:", key) - } - return err - } - if s.Debug { - log.Println("[LevelDB]Del: ", key) - } - return err -} - -// Close implements CacheStore -func (s *LevelDBStore) Close() { - s.store.Close() -} diff --git a/caches/leveldb_test.go b/caches/leveldb_test.go deleted file mode 100644 index 35981db1..00000000 --- a/caches/leveldb_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestLevelDBStore(t *testing.T) { - store, err := NewLevelDBStore("./level.db") - assert.NoError(t, err) - - var kvs = map[string]interface{}{ - "a": "b", - } - for k, v := range kvs { - assert.NoError(t, store.Put(k, v)) - } - - for k, v := range kvs { - val, err := store.Get(k) - assert.NoError(t, err) - assert.EqualValues(t, v, val) - } - - for k := range kvs { - err := store.Del(k) - assert.NoError(t, err) - } - - for k := range kvs { - _, err := store.Get(k) - assert.EqualValues(t, ErrNotExist, err) - } -} diff --git a/caches/lru.go b/caches/lru.go deleted file mode 100644 index 885f02d6..00000000 --- a/caches/lru.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright 2015 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "container/list" - "fmt" - "sync" - "time" -) - -// LRUCacher implments cache object facilities -type LRUCacher struct { - idList *list.List - sqlList *list.List - idIndex map[string]map[string]*list.Element - sqlIndex map[string]map[string]*list.Element - store CacheStore - mutex sync.Mutex - MaxElementSize int - Expired time.Duration - GcInterval time.Duration -} - -// NewLRUCacher creates a cacher -func NewLRUCacher(store CacheStore, maxElementSize int) *LRUCacher { - return NewLRUCacher2(store, 3600*time.Second, maxElementSize) -} - -// NewLRUCacher2 creates a cache include different params -func NewLRUCacher2(store CacheStore, expired time.Duration, maxElementSize int) *LRUCacher { - cacher := &LRUCacher{store: store, idList: list.New(), - sqlList: list.New(), Expired: expired, - GcInterval: CacheGcInterval, MaxElementSize: maxElementSize, - sqlIndex: make(map[string]map[string]*list.Element), - idIndex: make(map[string]map[string]*list.Element), - } - cacher.RunGC() - return cacher -} - -// RunGC run once every m.GcInterval -func (m *LRUCacher) RunGC() { - time.AfterFunc(m.GcInterval, func() { - m.RunGC() - m.GC() - }) -} - -// GC check ids lit and sql list to remove all element expired -func (m *LRUCacher) GC() { - m.mutex.Lock() - defer m.mutex.Unlock() - var removedNum int - for e := m.idList.Front(); e != nil; { - if removedNum <= CacheGcMaxRemoved && - time.Since(e.Value.(*idNode).lastVisit) > m.Expired { - removedNum++ - next := e.Next() - node := e.Value.(*idNode) - m.delBean(node.tbName, node.id) - e = next - } else { - break - } - } - - removedNum = 0 - for e := m.sqlList.Front(); e != nil; { - if removedNum <= CacheGcMaxRemoved && - time.Since(e.Value.(*sqlNode).lastVisit) > m.Expired { - removedNum++ - next := e.Next() - node := e.Value.(*sqlNode) - m.delIds(node.tbName, node.sql) - e = next - } else { - break - } - } -} - -// GetIds returns all bean's ids according to sql and parameter from cache -func (m *LRUCacher) GetIds(tableName, sql string) interface{} { - m.mutex.Lock() - defer m.mutex.Unlock() - if _, ok := m.sqlIndex[tableName]; !ok { - m.sqlIndex[tableName] = make(map[string]*list.Element) - } - if v, err := m.store.Get(sql); err == nil { - if el, ok := m.sqlIndex[tableName][sql]; !ok { - el = m.sqlList.PushBack(newSQLNode(tableName, sql)) - m.sqlIndex[tableName][sql] = el - } else { - lastTime := el.Value.(*sqlNode).lastVisit - // if expired, remove the node and return nil - if time.Since(lastTime) > m.Expired { - m.delIds(tableName, sql) - return nil - } - m.sqlList.MoveToBack(el) - el.Value.(*sqlNode).lastVisit = time.Now() - } - return v - } - - m.delIds(tableName, sql) - return nil -} - -// GetBean returns bean according tableName and id from cache -func (m *LRUCacher) GetBean(tableName string, id string) interface{} { - m.mutex.Lock() - defer m.mutex.Unlock() - if _, ok := m.idIndex[tableName]; !ok { - m.idIndex[tableName] = make(map[string]*list.Element) - } - tid := genID(tableName, id) - if v, err := m.store.Get(tid); err == nil { - if el, ok := m.idIndex[tableName][id]; ok { - lastTime := el.Value.(*idNode).lastVisit - // if expired, remove the node and return nil - if time.Since(lastTime) > m.Expired { - m.delBean(tableName, id) - return nil - } - m.idList.MoveToBack(el) - el.Value.(*idNode).lastVisit = time.Now() - } else { - el = m.idList.PushBack(newIDNode(tableName, id)) - m.idIndex[tableName][id] = el - } - return v - } - - // store bean is not exist, then remove memory's index - m.delBean(tableName, id) - return nil -} - -// clearIds clears all sql-ids mapping on table tableName from cache -func (m *LRUCacher) clearIds(tableName string) { - if tis, ok := m.sqlIndex[tableName]; ok { - for sql, v := range tis { - m.sqlList.Remove(v) - _ = m.store.Del(sql) - } - } - m.sqlIndex[tableName] = make(map[string]*list.Element) -} - -// ClearIds clears all sql-ids mapping on table tableName from cache -func (m *LRUCacher) ClearIds(tableName string) { - m.mutex.Lock() - m.clearIds(tableName) - m.mutex.Unlock() -} - -func (m *LRUCacher) clearBeans(tableName string) { - if tis, ok := m.idIndex[tableName]; ok { - for id, v := range tis { - m.idList.Remove(v) - tid := genID(tableName, id) - _ = m.store.Del(tid) - } - } - m.idIndex[tableName] = make(map[string]*list.Element) -} - -// ClearBeans clears all beans in some table -func (m *LRUCacher) ClearBeans(tableName string) { - m.mutex.Lock() - m.clearBeans(tableName) - m.mutex.Unlock() -} - -// PutIds pus ids into table -func (m *LRUCacher) PutIds(tableName, sql string, ids interface{}) { - m.mutex.Lock() - if _, ok := m.sqlIndex[tableName]; !ok { - m.sqlIndex[tableName] = make(map[string]*list.Element) - } - if el, ok := m.sqlIndex[tableName][sql]; !ok { - el = m.sqlList.PushBack(newSQLNode(tableName, sql)) - m.sqlIndex[tableName][sql] = el - } else { - el.Value.(*sqlNode).lastVisit = time.Now() - } - _ = m.store.Put(sql, ids) - if m.sqlList.Len() > m.MaxElementSize { - e := m.sqlList.Front() - node := e.Value.(*sqlNode) - m.delIds(node.tbName, node.sql) - } - m.mutex.Unlock() -} - -// PutBean puts beans into table -func (m *LRUCacher) PutBean(tableName string, id string, obj interface{}) { - m.mutex.Lock() - var el *list.Element - var ok bool - - if el, ok = m.idIndex[tableName][id]; !ok { - el = m.idList.PushBack(newIDNode(tableName, id)) - m.idIndex[tableName][id] = el - } else { - el.Value.(*idNode).lastVisit = time.Now() - } - - _ = m.store.Put(genID(tableName, id), obj) - if m.idList.Len() > m.MaxElementSize { - e := m.idList.Front() - node := e.Value.(*idNode) - m.delBean(node.tbName, node.id) - } - m.mutex.Unlock() -} - -func (m *LRUCacher) delIds(tableName, sql string) { - if _, ok := m.sqlIndex[tableName]; ok { - if el, ok := m.sqlIndex[tableName][sql]; ok { - delete(m.sqlIndex[tableName], sql) - m.sqlList.Remove(el) - } - } - _ = m.store.Del(sql) -} - -// DelIds deletes ids -func (m *LRUCacher) DelIds(tableName, sql string) { - m.mutex.Lock() - m.delIds(tableName, sql) - m.mutex.Unlock() -} - -func (m *LRUCacher) delBean(tableName string, id string) { - tid := genID(tableName, id) - if el, ok := m.idIndex[tableName][id]; ok { - delete(m.idIndex[tableName], id) - m.idList.Remove(el) - m.clearIds(tableName) - } - _ = m.store.Del(tid) -} - -// DelBean deletes beans in some table -func (m *LRUCacher) DelBean(tableName string, id string) { - m.mutex.Lock() - m.delBean(tableName, id) - m.mutex.Unlock() -} - -type idNode struct { - tbName string - id string - lastVisit time.Time -} - -type sqlNode struct { - tbName string - sql string - lastVisit time.Time -} - -func genID(prefix string, id string) string { - return fmt.Sprintf("%s-%s", prefix, id) -} - -func newIDNode(tbName string, id string) *idNode { - return &idNode{tbName, id, time.Now()} -} - -func newSQLNode(tbName, sql string) *sqlNode { - return &sqlNode{tbName, sql, time.Now()} -} diff --git a/caches/lru_test.go b/caches/lru_test.go deleted file mode 100644 index 771b924c..00000000 --- a/caches/lru_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2015 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "xorm.io/xorm/schemas" -) - -func TestLRUCache(t *testing.T) { - type CacheObject1 struct { - Id int64 - } - - store := NewMemoryStore() - cacher := NewLRUCacher(store, 10000) - - tableName := "cache_object1" - pks := []schemas.PK{ - {1}, - {2}, - } - - for _, pk := range pks { - sid, err := pk.ToString() - assert.NoError(t, err) - - cacher.PutIds(tableName, "select * from cache_object1", sid) - ids := cacher.GetIds(tableName, "select * from cache_object1") - assert.EqualValues(t, sid, ids) - - cacher.ClearIds(tableName) - ids2 := cacher.GetIds(tableName, "select * from cache_object1") - assert.Nil(t, ids2) - - obj2 := cacher.GetBean(tableName, sid) - assert.Nil(t, obj2) - - var obj = new(CacheObject1) - cacher.PutBean(tableName, sid, obj) - obj3 := cacher.GetBean(tableName, sid) - assert.EqualValues(t, obj, obj3) - - cacher.DelBean(tableName, sid) - obj4 := cacher.GetBean(tableName, sid) - assert.Nil(t, obj4) - } -} diff --git a/caches/manager.go b/caches/manager.go deleted file mode 100644 index 89a14106..00000000 --- a/caches/manager.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2020 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import "sync" - -// Manager represents a cache manager -type Manager struct { - cacher Cacher - disableGlobalCache bool - - cachers map[string]Cacher - cacherLock sync.RWMutex -} - -// NewManager creates a cache manager -func NewManager() *Manager { - return &Manager{ - cachers: make(map[string]Cacher), - } -} - -// SetDisableGlobalCache disable global cache or not -func (mgr *Manager) SetDisableGlobalCache(disable bool) { - if mgr.disableGlobalCache != disable { - mgr.disableGlobalCache = disable - } -} - -// SetCacher set cacher of table -func (mgr *Manager) SetCacher(tableName string, cacher Cacher) { - mgr.cacherLock.Lock() - mgr.cachers[tableName] = cacher - mgr.cacherLock.Unlock() -} - -// GetCacher returns a cache of a table -func (mgr *Manager) GetCacher(tableName string) Cacher { - var cacher Cacher - var ok bool - mgr.cacherLock.RLock() - cacher, ok = mgr.cachers[tableName] - mgr.cacherLock.RUnlock() - if !ok && !mgr.disableGlobalCache { - cacher = mgr.cacher - } - return cacher -} - -// SetDefaultCacher set the default cacher. Xorm's default not enable cacher. -func (mgr *Manager) SetDefaultCacher(cacher Cacher) { - mgr.cacher = cacher -} - -// GetDefaultCacher returns the default cacher -func (mgr *Manager) GetDefaultCacher() Cacher { - return mgr.cacher -} diff --git a/caches/memory_store.go b/caches/memory_store.go deleted file mode 100644 index f16254d8..00000000 --- a/caches/memory_store.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "sync" -) - -var _ CacheStore = NewMemoryStore() - -// MemoryStore represents in-memory store -type MemoryStore struct { - store map[interface{}]interface{} - mutex sync.RWMutex -} - -// NewMemoryStore creates a new store in memory -func NewMemoryStore() *MemoryStore { - return &MemoryStore{store: make(map[interface{}]interface{})} -} - -// Put puts object into store -func (s *MemoryStore) Put(key string, value interface{}) error { - s.mutex.Lock() - defer s.mutex.Unlock() - s.store[key] = value - return nil -} - -// Get gets object from store -func (s *MemoryStore) Get(key string) (interface{}, error) { - s.mutex.RLock() - defer s.mutex.RUnlock() - if v, ok := s.store[key]; ok { - return v, nil - } - - return nil, ErrNotExist -} - -// Del deletes object -func (s *MemoryStore) Del(key string) error { - s.mutex.Lock() - defer s.mutex.Unlock() - delete(s.store, key) - return nil -} diff --git a/caches/memory_store_test.go b/caches/memory_store_test.go deleted file mode 100644 index 12db4ea7..00000000 --- a/caches/memory_store_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package caches - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestMemoryStore(t *testing.T) { - store := NewMemoryStore() - var kvs = map[string]interface{}{ - "a": "b", - } - for k, v := range kvs { - assert.NoError(t, store.Put(k, v)) - } - - for k, v := range kvs { - val, err := store.Get(k) - assert.NoError(t, err) - assert.EqualValues(t, v, val) - } - - for k := range kvs { - err := store.Del(k) - assert.NoError(t, err) - } - - for k := range kvs { - _, err := store.Get(k) - assert.EqualValues(t, ErrNotExist, err) - } -} diff --git a/session_cols.go b/columns.go similarity index 84% rename from session_cols.go rename to columns.go index ca3589ab..6bc5314a 100644 --- a/session_cols.go +++ b/columns.go @@ -9,10 +9,10 @@ import ( "strings" "time" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) -func setColumnInt(bean interface{}, col *schemas.Column, t int64) { +func setColumnInt(bean any, col *schemas.Column, t int64) { v, err := col.ValueOf(bean) if err != nil { return @@ -27,7 +27,7 @@ func setColumnInt(bean interface{}, col *schemas.Column, t int64) { } } -func setColumnTime(bean interface{}, col *schemas.Column, t time.Time) { +func setColumnTime(bean any, col *schemas.Column, t time.Time) { v, err := col.ValueOf(bean) if err != nil { return @@ -64,19 +64,19 @@ func getFlagForColumn(m map[string]bool, col *schemas.Column) (val bool, has boo } // Incr provides a query string like "count = count + 1" -func (session *Session) Incr(column string, arg ...interface{}) *Session { +func (session *Session) Incr(column string, arg ...any) *Session { session.statement.Incr(column, arg...) return session } // Decr provides a query string like "count = count - 1" -func (session *Session) Decr(column string, arg ...interface{}) *Session { +func (session *Session) Decr(column string, arg ...any) *Session { session.statement.Decr(column, arg...) return session } // SetExpr provides a query string like "column = {expression}" -func (session *Session) SetExpr(column string, expression interface{}) *Session { +func (session *Session) SetExpr(column string, expression any) *Session { session.statement.SetExpr(column, expression) return session } @@ -115,9 +115,7 @@ func (session *Session) UseBool(columns ...string) *Session { return session } -// Distinct use for distinct columns. Caution: when you are using cache, -// distinct will not be cached because cache system need id, -// but distinct will not provide id +// Distinct use for distinct columns. func (session *Session) Distinct(columns ...string) *Session { session.statement.Distinct(columns...) return session diff --git a/session_cond.go b/conditions.go similarity index 69% rename from session_cond.go rename to conditions.go index 25d17148..6688abf1 100644 --- a/session_cond.go +++ b/conditions.go @@ -8,43 +8,43 @@ import "xorm.io/builder" // SQL provides raw sql input parameter. When you have a complex SQL statement // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL. -func (session *Session) SQL(query interface{}, args ...interface{}) *Session { +func (session *Session) SQL(query any, args ...any) *Session { session.statement.SQL(query, args...) return session } // Where provides custom query condition. -func (session *Session) Where(query interface{}, args ...interface{}) *Session { +func (session *Session) Where(query any, args ...any) *Session { session.statement.Where(query, args...) return session } // And provides custom query condition. -func (session *Session) And(query interface{}, args ...interface{}) *Session { +func (session *Session) And(query any, args ...any) *Session { session.statement.And(query, args...) return session } // Or provides custom query condition. -func (session *Session) Or(query interface{}, args ...interface{}) *Session { +func (session *Session) Or(query any, args ...any) *Session { session.statement.Or(query, args...) return session } // ID provides converting id as a query condition -func (session *Session) ID(id interface{}) *Session { +func (session *Session) ID(id any) *Session { session.statement.ID(id) return session } // In provides a query string like "id in (1, 2, 3)" -func (session *Session) In(column string, args ...interface{}) *Session { +func (session *Session) In(column string, args ...any) *Session { session.statement.In(column, args...) return session } // NotIn provides a query string like "id in (1, 2, 3)" -func (session *Session) NotIn(column string, args ...interface{}) *Session { +func (session *Session) NotIn(column string, args ...any) *Session { session.statement.NotIn(column, args...) return session } diff --git a/contexts/context_cache.go b/contexts/context_cache.go index 0d0f0f02..f7d24df7 100644 --- a/contexts/context_cache.go +++ b/contexts/context_cache.go @@ -7,24 +7,24 @@ package contexts // ContextCache is the interface that operates the cache data. type ContextCache interface { // Put puts value into cache with key. - Put(key string, val interface{}) + Put(key string, val any) // Get gets cached value by given key. - Get(key string) interface{} + Get(key string) any } -type memoryContextCache map[string]interface{} +type memoryContextCache map[string]any // NewMemoryContextCache return memoryContextCache func NewMemoryContextCache() memoryContextCache { - return make(map[string]interface{}) + return make(map[string]any) } // Put puts value into cache with key. -func (m memoryContextCache) Put(key string, val interface{}) { +func (m memoryContextCache) Put(key string, val any) { m[key] = val } // Get gets cached value by given key. -func (m memoryContextCache) Get(key string) interface{} { +func (m memoryContextCache) Get(key string) any { return m[key] } diff --git a/contexts/hook.go b/contexts/hook.go index f6d86cfc..a6d22253 100644 --- a/contexts/hook.go +++ b/contexts/hook.go @@ -14,15 +14,15 @@ import ( type ContextHook struct { start time.Time Ctx context.Context - SQL string // log content or SQL - Args []interface{} // if it's a SQL, it's the arguments + SQL string // log content or SQL + Args []any // if it's a SQL, it's the arguments Result sql.Result ExecuteTime time.Duration Err error // SQL executed error } // NewContextHook return context for hook -func NewContextHook(ctx context.Context, sql string, args []interface{}) *ContextHook { +func NewContextHook(ctx context.Context, sql string, args []any) *ContextHook { return &ContextHook{ start: time.Now(), Ctx: ctx, diff --git a/delete.go b/delete.go new file mode 100644 index 00000000..4f1bd878 --- /dev/null +++ b/delete.go @@ -0,0 +1,121 @@ +// Copyright 2016 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "errors" + + "xorm.io/builder" +) + +// ErrNeedDeletedCond delete needs less one condition error +var ErrNeedDeletedCond = errors.New("Delete action needs at least one condition") + +// Delete records, bean's non-empty fields are conditions +// At least one condition must be set. +func (session *Session) Delete(beans ...any) (int64, error) { + return session.delete(beans, true) +} + +// Truncate records, bean's non-empty fields are conditions +// In contrast to Delete this method allows deletes without conditions. +func (session *Session) Truncate(beans ...any) (int64, error) { + return session.delete(beans, false) +} + +func (session *Session) delete(beans []any, mustHaveConditions bool) (int64, error) { + if session.isAutoClose { + defer session.Close() + } + + if session.statement.LastError != nil { + return 0, session.statement.LastError + } + + var ( + err error + bean any + ) + if len(beans) > 0 { + bean = beans[0] + if err = session.statement.SetRefBean(bean); err != nil { + return 0, err + } + + executeBeforeClosures(session, bean) + + if processor, ok := any(bean).(BeforeDeleteProcessor); ok { + processor.BeforeDelete() + } + + if err = session.statement.MergeConds(bean); err != nil { + return 0, err + } + } + + pLimitN := session.statement.LimitN + if mustHaveConditions && !session.statement.Conds().IsValid() && (pLimitN == nil || *pLimitN == 0) { + return 0, ErrNeedDeletedCond + } + + table := session.statement.RefTable + + realSQLWriter := builder.NewWriter() + if err := session.statement.WriteDelete(realSQLWriter, session.engine.nowTime); err != nil { + return 0, err + } + + // if tag "deleted" is enabled, then set the field as deleted value + if !session.statement.GetUnscoped() && table != nil && table.DeletedColumn() != nil { + deletedColumn := table.DeletedColumn() + _, t, err := session.engine.nowTime(deletedColumn) + if err != nil { + return 0, err + } + + colName := deletedColumn.Name + session.afterClosures = append(session.afterClosures, func(bean any) { + col := table.GetColumn(colName) + setColumnTime(bean, col, t) + }) + } + + session.statement.RefTable = table + res, err := session.exec(realSQLWriter.String(), realSQLWriter.Args()...) + if err != nil { + return 0, err + } + + if bean != nil { + // handle after delete processors + if session.isAutoCommit { + for _, closure := range session.afterClosures { + closure(bean) + } + if processor, ok := any(bean).(AfterDeleteProcessor); ok { + processor.AfterDelete() + } + } else { + lenAfterClosures := len(session.afterClosures) + if lenAfterClosures > 0 && len(beans) > 0 { + if value, has := session.afterDeleteBeans[beans[0]]; has && value != nil { + *value = append(*value, session.afterClosures...) + } else { + afterClosures := make([]func(any), lenAfterClosures) + copy(afterClosures, session.afterClosures) + session.afterDeleteBeans[bean] = &afterClosures + } + } else { + if _, ok := any(bean).(AfterDeleteProcessor); ok { + session.afterDeleteBeans[bean] = nil + } + } + } + } + cleanupProcessorsClosures(&session.afterClosures) + // -- + + return res.RowsAffected() +} diff --git a/dialects/dameng.go b/dialects/dameng.go index 38f571fb..6614dc6f 100644 --- a/dialects/dameng.go +++ b/dialects/dameng.go @@ -13,10 +13,10 @@ import ( "strconv" "strings" - "xorm.io/xorm/convert" - "xorm.io/xorm/core" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) func init() { @@ -749,14 +749,14 @@ func (db *dameng) SetQuotePolicy(quotePolicy QuotePolicy) { } } -func (db *dameng) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { - args := []interface{}{tableName, idxName} +func (db *dameng) IndexCheckSQL(tableName, idxName string) (string, []any) { + args := []any{tableName, idxName} return `SELECT INDEX_NAME FROM USER_INDEXES ` + `WHERE TABLE_NAME = ? AND INDEX_NAME = ?`, args } -func (db *dameng) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { - return db.HasRecords(queryer, ctx, `SELECT table_name FROM user_tables WHERE table_name = ?`, tableName) +func (db *dameng) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { + return db.HasRecords(ctx, queryer, `SELECT table_name FROM user_tables WHERE table_name = ?`, tableName) } func (db *dameng) IsSequenceExist(ctx context.Context, queryer core.Queryer, seqName string) (bool, error) { @@ -779,11 +779,11 @@ func (db *dameng) IsSequenceExist(ctx context.Context, queryer core.Queryer, seq return cnt > 0, nil } -func (db *dameng) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { - args := []interface{}{tableName, colName} +func (db *dameng) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { + args := []any{tableName, colName} query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = ?" + " AND column_name = ?" - return db.HasRecords(queryer, ctx, query, args...) + return db.HasRecords(ctx, queryer, query, args...) } var _ sql.Scanner = &dmClobScanner{} @@ -800,7 +800,7 @@ type dmClobObject interface { // var _ dmClobObject = &dm.DmClob{} -func (d *dmClobScanner) Scan(data interface{}) error { +func (d *dmClobScanner) Scan(data any) error { if data == nil { return nil } @@ -850,7 +850,7 @@ func addSingleQuote(name string) string { return b.String() } -func (db *dameng) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { +func (db *dameng) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { s := `select column_name from user_cons_columns where constraint_name = (select constraint_name from user_constraints where table_name = ? and constraint_type ='P')` @@ -925,7 +925,7 @@ func (db *dameng) GetColumns(queryer core.Queryer, ctx context.Context, tableNam } if utils.IndexSlice(pkNames, col.Name) > -1 { col.IsPrimaryKey = true - has, err := db.HasRecords(queryer, ctx, "SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = ?", utils.SeqName(tableName)) + has, err := db.HasRecords(ctx, queryer, "SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = ?", utils.SeqName(tableName)) if err != nil { return nil, nil, err } @@ -1002,9 +1002,9 @@ func (db *dameng) GetColumns(queryer core.Queryer, ctx context.Context, tableNam return colSeq, cols, nil } -func (db *dameng) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { +func (db *dameng) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { s := "SELECT table_name FROM user_tables WHERE temporary = 'N' AND table_name NOT LIKE ?" - args := []interface{}{strings.ToUpper(db.uri.User), "%$%"} + args := []any{strings.ToUpper(db.uri.User), "%$%"} rows, err := queryer.QueryContext(ctx, s, args...) if err != nil { @@ -1028,8 +1028,8 @@ func (db *dameng) GetTables(queryer core.Queryer, ctx context.Context) ([]*schem return tables, nil } -func (db *dameng) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{tableName, tableName} +func (db *dameng) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{tableName, tableName} s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + "WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =?" + " AND t.index_name not in (SELECT index_name FROM ALL_CONSTRAINTS WHERE CONSTRAINT_TYPE='P' AND table_name = ?)" @@ -1120,7 +1120,7 @@ func (d *damengDriver) Parse(driverName, dataSourceName string) (*URI, error) { }, nil } -func (d *damengDriver) GenScanResult(colType string) (interface{}, error) { +func (d *damengDriver) GenScanResult(colType string) (any, error) { switch colType { case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB": var s sql.NullString @@ -1149,13 +1149,13 @@ func (d *damengDriver) GenScanResult(colType string) (interface{}, error) { } } -func (d *damengDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, vv ...interface{}) error { - scanResults := make([]interface{}, 0, len(types)) +func (d *damengDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, vv ...any) error { + scanResults := make([]any, 0, len(types)) replaces := make([]bool, 0, len(types)) var err error for i, v := range vv { var replaced bool - var scanResult interface{} + var scanResult any switch types[i].DatabaseTypeName() { case "CLOB", "TEXT": scanResult = &dmClobScanner{} @@ -1179,7 +1179,7 @@ func (d *damengDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.Colu if replaced { switch t := scanResults[i].(type) { case *dmClobScanner: - var d interface{} + var d any if t.valid { d = t.data } else { diff --git a/dialects/dialect.go b/dialects/dialect.go index 8e512c4f..b1d26c63 100644 --- a/dialects/dialect.go +++ b/dialects/dialect.go @@ -10,8 +10,8 @@ import ( "strings" "time" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) // URI represents an uri to visit database @@ -66,13 +66,13 @@ type Dialect interface { AutoIncrStr() string - GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) - IndexCheckSQL(tableName, idxName string) (string, []interface{}) + GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) + IndexCheckSQL(tableName, idxName string) (string, []any) CreateIndexSQL(tableName string, index *schemas.Index) string DropIndexSQL(tableName string, index *schemas.Index) string - GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) - IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) + GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) + IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) CreateTableSQL(ctx context.Context, queryer core.Queryer, table *schemas.Table, tableName string) (string, bool, error) DropTableSQL(tableName string) (string, bool) @@ -80,8 +80,8 @@ type Dialect interface { IsSequenceExist(ctx context.Context, queryer core.Queryer, seqName string) (bool, error) DropSequenceSQL(seqName string) (string, error) - GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) - IsColumnExist(queryer core.Queryer, ctx context.Context, tableName string, colName string) (bool, error) + GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) + IsColumnExist(ctx context.Context, queryer core.Queryer, tableName string, colName string) (bool, error) AddColumnSQL(tableName string, col *schemas.Column) string ModifyColumnSQL(tableName string, col *schemas.Column) string @@ -177,7 +177,7 @@ func (db *Base) DropTableSQL(tableName string) (string, bool) { } // HasRecords returns true if the SQL has records returned -func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query string, args ...interface{}) (bool, error) { +func (db *Base) HasRecords(ctx context.Context, queryer core.Queryer, query string, args ...any) (bool, error) { rows, err := queryer.QueryContext(ctx, query, args...) if err != nil { return false, err @@ -191,7 +191,7 @@ func (db *Base) HasRecords(queryer core.Queryer, ctx context.Context, query stri } // IsColumnExist returns true if the column of the table exist -func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { +func (db *Base) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { quote := db.dialect.Quoter().Quote query := fmt.Sprintf( "SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?", @@ -202,7 +202,7 @@ func (db *Base) IsColumnExist(queryer core.Queryer, ctx context.Context, tableNa quote("TABLE_NAME"), quote("COLUMN_NAME"), ) - return db.HasRecords(queryer, ctx, query, db.uri.DBName, tableName, colName) + return db.HasRecords(ctx, queryer, query, db.uri.DBName, tableName, colName) } // AddColumnSQL returns a SQL to add a column @@ -274,7 +274,6 @@ func regDrvsNDialects() bool { "mssql": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, "odbc": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access "mysql": {"mysql", func() Driver { return &mysqlDriver{} }, func() Dialect { return &mysql{} }}, - "mymysql": {"mysql", func() Driver { return &mymysqlDriver{} }, func() Dialect { return &mysql{} }}, "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }}, "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }}, "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, diff --git a/dialects/driver.go b/dialects/driver.go index c63dbfa3..43ac9a7c 100644 --- a/dialects/driver.go +++ b/dialects/driver.go @@ -9,7 +9,7 @@ import ( "fmt" "time" - "xorm.io/xorm/core" + "xorm.io/xorm/v2/internal/core" ) // ScanContext represents a context when Scan @@ -27,13 +27,11 @@ type DriverFeatures struct { type Driver interface { Parse(string, string) (*URI, error) Features() *DriverFeatures - GenScanResult(string) (interface{}, error) // according given column type generating a suitable scan interface - Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...interface{}) error + GenScanResult(string) (any, error) // according given column type generating a suitable scan interface + Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...any) error } -var ( - drivers = map[string]Driver{} -) +var drivers = map[string]Driver{} // RegisterDriver register a driver func RegisterDriver(driverName string, driver Driver) { @@ -80,6 +78,6 @@ func OpenDialect(driverName, connstr string) (Dialect, error) { type baseDriver struct{} -func (b *baseDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, v ...interface{}) error { +func (b *baseDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, v ...any) error { return rows.Scan(v...) } diff --git a/dialects/mssql.go b/dialects/mssql.go index 26d76c45..154bfd23 100644 --- a/dialects/mssql.go +++ b/dialects/mssql.go @@ -13,8 +13,8 @@ import ( "strconv" "strings" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) var ( @@ -438,25 +438,25 @@ func (db *mssql) ModifyColumnSQL(tableName string, col *schemas.Column) string { return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s", db.quoter.Quote(tableName), s) } -func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { - args := []interface{}{idxName} +func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []any) { + args := []any{idxName} sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?" return sql, args } -func (db *mssql) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { +func (db *mssql) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { query := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?` - return db.HasRecords(queryer, ctx, query, tableName, colName) + return db.HasRecords(ctx, queryer, query, tableName, colName) } -func (db *mssql) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { +func (db *mssql) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { sql := "select * from sysobjects where id = object_id(N'" + tableName + "') and OBJECTPROPERTY(id, N'IsUserTable') = 1" - return db.HasRecords(queryer, ctx, sql) + return db.HasRecords(ctx, queryer, sql) } -func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { - args := []interface{}{} +func (db *mssql) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { + args := []any{} s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable, "default_is_null" = (CASE WHEN c.text is null THEN 1 ELSE 0 END), replace(replace(isnull(c.text,''),'(',''),')','') as vdefault, @@ -549,8 +549,8 @@ func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName return colSeq, cols, nil } -func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { - args := []interface{}{} +func (db *mssql) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { + args := []any{} s := `select name from sysobjects where xtype ='U'` rows, err := queryer.QueryContext(ctx, s, args...) @@ -576,8 +576,8 @@ func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema return tables, nil } -func (db *mssql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{tableName} +func (db *mssql) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{tableName} s := `SELECT IXS.NAME AS [INDEX_NAME], C.NAME AS [COLUMN_NAME], @@ -715,7 +715,7 @@ func (p *odbcDriver) Parse(driverName, dataSourceName string) (*URI, error) { return &URI{DBName: dbName, DBType: schemas.MSSQL}, nil } -func (p *odbcDriver) GenScanResult(colType string) (interface{}, error) { +func (p *odbcDriver) GenScanResult(colType string) (any, error) { switch colType { case "VARCHAR", "TEXT", "CHAR", "NVARCHAR", "NCHAR", "NTEXT": fallthrough diff --git a/dialects/mysql.go b/dialects/mysql.go index d11c728b..b7db3566 100644 --- a/dialects/mysql.go +++ b/dialects/mysql.go @@ -12,10 +12,9 @@ import ( "regexp" "strconv" "strings" - "time" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) var ( @@ -371,16 +370,16 @@ func (db *mysql) AutoIncrStr() string { return "AUTO_INCREMENT" } -func (db *mysql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { - args := []interface{}{db.uri.DBName, tableName, idxName} +func (db *mysql) IndexCheckSQL(tableName, idxName string) (string, []any) { + args := []any{db.uri.DBName, tableName, idxName} sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`" sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?" return sql, args } -func (db *mysql) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { +func (db *mysql) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?" - return db.HasRecords(queryer, ctx, sql, db.uri.DBName, tableName) + return db.HasRecords(ctx, queryer, sql, db.uri.DBName, tableName) } func (db *mysql) AddColumnSQL(tableName string, col *schemas.Column) string { @@ -408,8 +407,8 @@ func (db *mysql) ModifyColumnSQL(tableName string, col *schemas.Column) string { return fmt.Sprintf("ALTER TABLE %s MODIFY COLUMN %s", db.quoter.Quote(tableName), s) } -func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { - args := []interface{}{db.uri.DBName, tableName} +func (db *mysql) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { + args := []any{db.uri.DBName, tableName} alreadyQuoted := "(INSTR(VERSION(), 'maria') > 0 && " + "(SUBSTRING_INDEX(VERSION(), '.', 1) > 10 || " + "(SUBSTRING_INDEX(VERSION(), '.', 1) = 10 && " + @@ -545,8 +544,8 @@ func (db *mysql) GetColumns(queryer core.Queryer, ctx context.Context, tableName return colSeq, cols, nil } -func (db *mysql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { - args := []interface{}{db.uri.DBName} +func (db *mysql) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { + args := []any{db.uri.DBName} s := "SELECT `TABLE_NAME`, `ENGINE`, `AUTO_INCREMENT`, `TABLE_COMMENT`, `TABLE_COLLATION` from " + "`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB' OR `ENGINE` = 'TokuDB')" @@ -597,8 +596,8 @@ func (db *mysql) SetQuotePolicy(quotePolicy QuotePolicy) { } } -func (db *mysql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{db.uri.DBName, tableName} +func (db *mysql) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{db.uri.DBName, tableName} s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? ORDER BY `SEQ_IN_INDEX`" rows, err := queryer.QueryContext(ctx, s, args...) @@ -760,7 +759,7 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) { return uri, nil } -func (p *mysqlDriver) GenScanResult(colType string) (interface{}, error) { +func (p *mysqlDriver) GenScanResult(colType string) (any, error) { colType = strings.Replace(colType, "UNSIGNED ", "", -1) switch colType { case "CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "ENUM", "SET", "JSON": @@ -792,56 +791,3 @@ func (p *mysqlDriver) GenScanResult(colType string) (interface{}, error) { return &r, nil } } - -type mymysqlDriver struct { - mysqlDriver -} - -func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) { - uri := &URI{DBType: schemas.MYSQL} - - pd := strings.SplitN(dataSourceName, "*", 2) - if len(pd) == 2 { - // Parse protocol part of URI - p := strings.SplitN(pd[0], ":", 2) - if len(p) != 2 { - return nil, errors.New("wrong protocol part of URI") - } - uri.Proto = p[0] - options := strings.Split(p[1], ",") - uri.Raddr = options[0] - for _, o := range options[1:] { - kv := strings.SplitN(o, "=", 2) - var k, v string - if len(kv) == 2 { - k, v = kv[0], kv[1] - } else { - k, v = o, "true" - } - switch k { - case "laddr": - uri.Laddr = v - case "timeout": - to, err := time.ParseDuration(v) - if err != nil { - return nil, err - } - uri.Timeout = to - default: - return nil, errors.New("unknown option: " + k) - } - } - // Remove protocol part - pd = pd[1:] - } - // Parse database part of URI - dup := strings.SplitN(pd[0], "/", 3) - if len(dup) != 3 { - return nil, errors.New("Wrong database part of URI") - } - uri.DBName = dup[0] - uri.User = dup[1] - uri.Passwd = dup[2] - - return uri, nil -} diff --git a/dialects/oracle.go b/dialects/oracle.go index 5f614b1a..2164f3a9 100644 --- a/dialects/oracle.go +++ b/dialects/oracle.go @@ -13,8 +13,8 @@ import ( "strconv" "strings" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) var ( @@ -658,7 +658,7 @@ func (db *oracle) CreateTableSQL(ctx context.Context, queryer core.Queryer, tabl } func (db *oracle) IsSequenceExist(ctx context.Context, queryer core.Queryer, seqName string) (bool, error) { - return db.HasRecords(queryer, ctx, `SELECT sequence_name FROM user_sequences WHERE sequence_name = :1`, seqName) + return db.HasRecords(ctx, queryer, `SELECT sequence_name FROM user_sequences WHERE sequence_name = :1`, seqName) } func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) { @@ -678,25 +678,25 @@ func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) { } } -func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { - args := []interface{}{tableName, idxName} +func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []any) { + args := []any{tableName, idxName} return `SELECT INDEX_NAME FROM USER_INDEXES ` + `WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args } -func (db *oracle) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { - return db.HasRecords(queryer, ctx, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName) +func (db *oracle) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { + return db.HasRecords(ctx, queryer, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName) } -func (db *oracle) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { - args := []interface{}{tableName, colName} +func (db *oracle) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { + args := []any{tableName, colName} query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" + " AND column_name = :2" - return db.HasRecords(queryer, ctx, query, args...) + return db.HasRecords(ctx, queryer, query, args...) } -func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { - args := []interface{}{tableName} +func (db *oracle) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { + args := []any{tableName} s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," + "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1" @@ -795,8 +795,8 @@ func (db *oracle) GetColumns(queryer core.Queryer, ctx context.Context, tableNam return colSeq, cols, nil } -func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { - args := []interface{}{} +func (db *oracle) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { + args := []any{} s := "SELECT table_name FROM user_tables" rows, err := queryer.QueryContext(ctx, s, args...) @@ -821,8 +821,8 @@ func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schem return tables, nil } -func (db *oracle) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{tableName} +func (db *oracle) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{tableName} s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + "WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1" @@ -911,7 +911,7 @@ func (g *godrorDriver) Parse(driverName, dataSourceName string) (*URI, error) { return db, nil } -func (g *godrorDriver) GenScanResult(colType string) (interface{}, error) { +func (g *godrorDriver) GenScanResult(colType string) (any, error) { switch colType { case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB": var s sql.NullString diff --git a/dialects/postgres.go b/dialects/postgres.go index 6e379583..e436dfb6 100644 --- a/dialects/postgres.go +++ b/dialects/postgres.go @@ -13,8 +13,8 @@ import ( "strconv" "strings" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) // from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html @@ -998,23 +998,23 @@ func (db *postgres) AutoIncrStr() string { return "" } -func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { +func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []any) { if len(db.getSchema()) == 0 { - args := []interface{}{tableName, idxName} + args := []any{tableName, idxName} return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args } - args := []interface{}{db.getSchema(), tableName, idxName} + args := []any{db.getSchema(), tableName, idxName} return `SELECT indexname FROM pg_indexes ` + `WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args } -func (db *postgres) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { +func (db *postgres) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { if len(db.getSchema()) == 0 { - return db.HasRecords(queryer, ctx, `SELECT tablename FROM pg_tables WHERE tablename = $1`, tableName) + return db.HasRecords(ctx, queryer, `SELECT tablename FROM pg_tables WHERE tablename = $1`, tableName) } - return db.HasRecords(queryer, ctx, `SELECT tablename FROM pg_tables WHERE schemaname = $1 AND tablename = $2`, + return db.HasRecords(ctx, queryer, `SELECT tablename FROM pg_tables WHERE schemaname = $1 AND tablename = $2`, db.getSchema(), tableName) } @@ -1070,12 +1070,12 @@ func (db *postgres) DropIndexSQL(tableName string, index *schemas.Index) string return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName)) } -func (db *postgres) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { - args := []interface{}{db.getSchema(), tableName, colName} +func (db *postgres) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { + args := []any{db.getSchema(), tableName, colName} query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" + " AND column_name = $3" if len(db.getSchema()) == 0 { - args = []interface{}{tableName, colName} + args = []any{tableName, colName} query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" + " AND column_name = $2" } @@ -1092,8 +1092,8 @@ func (db *postgres) IsColumnExist(queryer core.Queryer, ctx context.Context, tab return false, rows.Err() } -func (db *postgres) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { - args := []interface{}{tableName} +func (db *postgres) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { + args := []any{tableName} s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, description, CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey, CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey @@ -1245,8 +1245,8 @@ WHERE n.nspname= s.table_schema AND c.relkind = 'r' AND c.relname = $1%s AND f.a return colSeq, cols, nil } -func (db *postgres) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { - args := []interface{}{} +func (db *postgres) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { + args := []any{} s := "SELECT tablename FROM pg_tables" schema := db.getSchema() if schema != "" { @@ -1288,8 +1288,8 @@ func getIndexColName(indexdef string) []string { return colNames } -func (db *postgres) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{tableName} +func (db *postgres) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{tableName} s := "SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1" if len(db.getSchema()) != 0 { args = append(args, db.getSchema()) @@ -1522,7 +1522,7 @@ func (p *pqDriver) Parse(driverName, dataSourceName string) (*URI, error) { return db, nil } -func (p *pqDriver) GenScanResult(colType string) (interface{}, error) { +func (p *pqDriver) GenScanResult(colType string) (any, error) { switch colType { case "VARCHAR", "TEXT": var s sql.NullString diff --git a/dialects/sqlite3.go b/dialects/sqlite3.go index 62519b6b..d6c341f1 100644 --- a/dialects/sqlite3.go +++ b/dialects/sqlite3.go @@ -12,8 +12,8 @@ import ( "regexp" "strings" - "xorm.io/xorm/core" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) var ( @@ -267,13 +267,13 @@ func (db *sqlite3) AutoIncrStr() string { return "AUTOINCREMENT" } -func (db *sqlite3) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { - args := []interface{}{idxName} +func (db *sqlite3) IndexCheckSQL(tableName, idxName string) (string, []any) { + args := []any{idxName} return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args } -func (db *sqlite3) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { - return db.HasRecords(queryer, ctx, "SELECT name FROM sqlite_master WHERE type='table' and name = ?", tableName) +func (db *sqlite3) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) { + return db.HasRecords(ctx, queryer, "SELECT name FROM sqlite_master WHERE type='table' and name = ?", tableName) } func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string { @@ -291,7 +291,7 @@ func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string { return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName)) } -func (db *sqlite3) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { +func (db *sqlite3) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) { query := "SELECT * FROM " + tableName + " LIMIT 0" rows, err := queryer.QueryContext(ctx, query) if err != nil { @@ -375,8 +375,8 @@ func parseString(colStr string) (*schemas.Column, error) { return col, nil } -func (db *sqlite3) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { - args := []interface{}{tableName} +func (db *sqlite3) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) { + args := []any{tableName} s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?" rows, err := queryer.QueryContext(ctx, s, args...) @@ -434,8 +434,8 @@ func (db *sqlite3) GetColumns(queryer core.Queryer, ctx context.Context, tableNa return colSeq, cols, nil } -func (db *sqlite3) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { - args := []interface{}{} +func (db *sqlite3) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) { + args := []any{} s := "SELECT name FROM sqlite_master WHERE type='table'" rows, err := queryer.QueryContext(ctx, s, args...) @@ -462,8 +462,8 @@ func (db *sqlite3) GetTables(queryer core.Queryer, ctx context.Context) ([]*sche return tables, nil } -func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { - args := []interface{}{tableName} +func (db *sqlite3) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) { + args := []any{tableName} s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?" rows, err := queryer.QueryContext(ctx, s, args...) @@ -547,7 +547,7 @@ func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*URI, error) { return &URI{DBType: schemas.SQLITE, DBName: dataSourceName}, nil } -func (p *sqlite3Driver) GenScanResult(colType string) (interface{}, error) { +func (p *sqlite3Driver) GenScanResult(colType string) (any, error) { switch colType { case "TEXT": var s sql.NullString diff --git a/dialects/table_name.go b/dialects/table_name.go index 8a0baeac..35e95d72 100644 --- a/dialects/table_name.go +++ b/dialects/table_name.go @@ -9,9 +9,9 @@ import ( "reflect" "strings" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" ) // TableNameWithSchema will add schema prefix on table name if possible @@ -25,7 +25,7 @@ func TableNameWithSchema(dialect Dialect, tableName string) string { } // TableNameNoSchema returns table name with given tableName -func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName interface{}) string { +func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName any) string { quote := dialect.Quoter().Quote switch tt := tableName.(type) { case []string: @@ -37,7 +37,7 @@ func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName interface } else if len(tt) == 1 { return quote(tt[0]) } - case []interface{}: + case []any: l := len(tt) var table string if l > 0 { @@ -84,7 +84,7 @@ func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName interface } // FullTableName returns table name with quote and schema according parameter -func FullTableName(dialect Dialect, mapper names.Mapper, bean interface{}, includeSchema ...bool) string { +func FullTableName(dialect Dialect, mapper names.Mapper, bean any, includeSchema ...bool) string { tbName := TableNameNoSchema(dialect, mapper, bean) if len(includeSchema) > 0 && includeSchema[0] && !utils.IsSubQuery(tbName) { tbName = TableNameWithSchema(dialect, tbName) diff --git a/dialects/table_name_test.go b/dialects/table_name_test.go index 66edc2b4..5bacaa98 100644 --- a/dialects/table_name_test.go +++ b/dialects/table_name_test.go @@ -7,7 +7,7 @@ package dialects import ( "testing" - "xorm.io/xorm/names" + "xorm.io/xorm/v2/names" "github.com/stretchr/testify/assert" ) diff --git a/dialects/time.go b/dialects/time.go index 4a6beb77..d3d3f21b 100644 --- a/dialects/time.go +++ b/dialects/time.go @@ -7,13 +7,13 @@ package dialects import ( "strings" "time" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) // FormatColumnTime format column time -func FormatColumnTime(dialect Dialect, dbLocation *time.Location, col *schemas.Column, t time.Time) (interface{}, error) { +func FormatColumnTime(dialect Dialect, dbLocation *time.Location, col *schemas.Column, t time.Time) (any, error) { if utils.IsTimeZero(t) { if col.Nullable { return nil, nil diff --git a/dialects/time_test.go b/dialects/time_test.go index 670207c6..6616c48e 100644 --- a/dialects/time_test.go +++ b/dialects/time_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) type dialect struct { @@ -31,7 +31,7 @@ func TestFormatColumnTime(t *testing.T) { location *time.Location column *schemas.Column time time.Time - wantRes interface{} + wantRes any wantErr error }{ { diff --git a/doc.go b/doc.go index f88f5371..6e22fe97 100644 --- a/doc.go +++ b/doc.go @@ -32,7 +32,7 @@ XORM supports raw SQL execution: results, err := engine.QueryString("select * from user") -3. query with a SQL string, the returned results is []map[string]interface{} +3. query with a SQL string, the returned results is []map[string]any results, err := engine.QueryInterface("select * from user") @@ -88,7 +88,7 @@ There are 8 major ORM methods and many helpful methods to use to operate databas 4. Query multiple records and record by record handle, there two methods, one is Iterate, another is Rows - err := engine.Iterate(new(User), func(i int, bean interface{}) error { + err := engine.Iterate(new(User), func(i int, bean any) error { // do something }) // SELECT * FROM user diff --git a/engine.go b/engine.go index 671f00f2..432b92ed 100644 --- a/engine.go +++ b/engine.go @@ -17,21 +17,19 @@ import ( "strings" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/contexts" - "xorm.io/xorm/core" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/log" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" - "xorm.io/xorm/tags" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" + "xorm.io/xorm/v2/tags" ) // Engine is the major struct of xorm, it means a database manager. // Commonly, an application only need one engine type Engine struct { - cacherMgr *caches.Manager defaultContext context.Context dialect dialects.Dialect driver dialects.Driver @@ -66,16 +64,14 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { } func newEngine(driverName, dataSourceName string, dialect dialects.Dialect, db *core.DB) (*Engine, error) { - cacherMgr := caches.NewManager() mapper := names.NewCacheMapper(new(names.SnakeMapper)) - tagParser := tags.NewParser("xorm", dialect, mapper, mapper, cacherMgr) + tagParser := tags.NewParser("xorm", dialect, mapper, mapper) engine := &Engine{ dialect: dialect, driver: dialects.QueryDriver(driverName), TZLocation: time.Local, defaultContext: context.Background(), - cacherMgr: cacherMgr, tagParser: tagParser, driverName: driverName, dataSourceName: dataSourceName, @@ -129,16 +125,6 @@ func (engine *Engine) EnableSessionID(enable bool) { engine.logSessionID = enable } -// SetCacher sets cacher for the table -func (engine *Engine) SetCacher(tableName string, cacher caches.Cacher) { - engine.cacherMgr.SetCacher(tableName, cacher) -} - -// GetCacher returns the cachher of the special table -func (engine *Engine) GetCacher(tableName string) caches.Cacher { - return engine.cacherMgr.GetCacher(tableName) -} - // SetQuotePolicy sets the special quote policy func (engine *Engine) SetQuotePolicy(quotePolicy dialects.QuotePolicy) { engine.dialect.SetQuotePolicy(quotePolicy) @@ -154,7 +140,7 @@ func (engine *Engine) BufferSize(size int) *Session { // ShowSQL show SQL statement or not on logger if log level is great than INFO func (engine *Engine) ShowSQL(show ...bool) { engine.logger.ShowSQL(show...) - engine.DB().Logger = engine.logger + engine.db.Logger = engine.logger } // Logger return the logger interface @@ -163,7 +149,7 @@ func (engine *Engine) Logger() log.ContextLogger { } // SetLogger set the new logger -func (engine *Engine) SetLogger(logger interface{}) { +func (engine *Engine) SetLogger(logger any) { var realLogger log.ContextLogger switch t := logger.(type) { case log.ContextLogger: @@ -174,7 +160,7 @@ func (engine *Engine) SetLogger(logger interface{}) { panic("logger should implement either log.ContextLogger or log.Logger") } engine.logger = realLogger - engine.DB().Logger = realLogger + engine.db.Logger = realLogger } // SetLogLevel sets the logger level @@ -182,11 +168,6 @@ func (engine *Engine) SetLogLevel(level log.LogLevel) { engine.logger.SetLevel(level) } -// SetDisableGlobalCache disable global cache or not -func (engine *Engine) SetDisableGlobalCache(disable bool) { - engine.cacherMgr.SetDisableGlobalCache(disable) -} - // DriverName return the current sql driver's name func (engine *Engine) DriverName() string { return engine.driverName @@ -251,40 +232,22 @@ func (engine *Engine) SQLType(c *schemas.Column) string { // SetConnMaxLifetime sets the maximum amount of time a connection may be reused. func (engine *Engine) SetConnMaxLifetime(d time.Duration) { - engine.DB().SetConnMaxLifetime(d) + engine.db.SetConnMaxLifetime(d) } // SetConnMaxIdleTime sets the maximum amount of time a connection may be idle. func (engine *Engine) SetConnMaxIdleTime(d time.Duration) { - engine.DB().SetConnMaxIdleTime(d) + engine.db.SetConnMaxIdleTime(d) } // SetMaxOpenConns is only available for go 1.2+ func (engine *Engine) SetMaxOpenConns(conns int) { - engine.DB().SetMaxOpenConns(conns) + engine.db.SetMaxOpenConns(conns) } // SetMaxIdleConns set the max idle connections on pool, default is 2 func (engine *Engine) SetMaxIdleConns(conns int) { - engine.DB().SetMaxIdleConns(conns) -} - -// SetDefaultCacher set the default cacher. Xorm's default not enable cacher. -func (engine *Engine) SetDefaultCacher(cacher caches.Cacher) { - engine.cacherMgr.SetDefaultCacher(cacher) -} - -// GetDefaultCacher returns the default cacher -func (engine *Engine) GetDefaultCacher() caches.Cacher { - return engine.cacherMgr.GetDefaultCacher() -} - -// NoCache If you has set default cacher, and you want temporilly stop use cache, -// you can use NoCache() -func (engine *Engine) NoCache() *Session { - session := engine.NewSession() - session.isAutoClose = true - return session.NoCache() + engine.db.SetMaxIdleConns(conns) } // NoCascade If you do not want to auto cascade load object @@ -294,22 +257,6 @@ func (engine *Engine) NoCascade() *Session { return session.NoCascade() } -// MapCacher Set a table use a special cacher -func (engine *Engine) MapCacher(bean interface{}, cacher caches.Cacher) error { - engine.SetCacher(dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean, true), cacher) - return nil -} - -// NewDB provides an interface to operate database directly -func (engine *Engine) NewDB() (*core.DB, error) { - return core.Open(engine.driverName, engine.dataSourceName) -} - -// DB return the wrapper of sql.DB -func (engine *Engine) DB() *core.DB { - return engine.db -} - // Dialect return database dialect func (engine *Engine) Dialect() dialects.Dialect { return engine.dialect @@ -322,7 +269,7 @@ func (engine *Engine) NewSession() *Session { // Close the engine func (engine *Engine) Close() error { - return engine.DB().Close() + return engine.db.Close() } // Ping tests if database is alive @@ -338,7 +285,7 @@ func (engine *Engine) Ping() error { // engine.SQL("select * from user").Find(&users) // // This code will execute "select * from user" and set the records to users -func (engine *Engine) SQL(query interface{}, args ...interface{}) *Session { +func (engine *Engine) SQL(query any, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.SQL(query, args...) @@ -361,14 +308,14 @@ func (engine *Engine) NoAutoCondition(no ...bool) *Session { } func (engine *Engine) loadTableInfo(ctx context.Context, table *schemas.Table) error { - colSeq, cols, err := engine.dialect.GetColumns(engine.db, ctx, table.Name) + colSeq, cols, err := engine.dialect.GetColumns(ctx, engine.db, table.Name) if err != nil { return err } for _, name := range colSeq { table.AddColumn(cols[name]) } - indexes, err := engine.dialect.GetIndexes(engine.db, ctx, table.Name) + indexes, err := engine.dialect.GetIndexes(ctx, engine.db, table.Name) if err != nil { return err } @@ -398,7 +345,7 @@ func (engine *Engine) loadTableInfo(ctx context.Context, table *schemas.Table) e // DBMetas Retrieve all tables, columns, indexes' informations from database. func (engine *Engine) DBMetas() ([]*schemas.Table, error) { - tables, err := engine.dialect.GetTables(engine.db, engine.defaultContext) + tables, err := engine.dialect.GetTables(engine.defaultContext, engine.db) if err != nil { return nil, err } @@ -481,8 +428,7 @@ func (engine *Engine) dumpTables(ctx context.Context, tables []*schemas.Table, w return err } } - cacherMgr := caches.NewManager() - dstTableCache := tags.NewParser("xorm", dstDialect, engine.GetTableMapper(), engine.GetColumnMapper(), cacherMgr) + dstTableCache := tags.NewParser("xorm", dstDialect, engine.GetTableMapper(), engine.GetColumnMapper()) _, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm %s, from %s to %s*/\n\n", time.Now().In(engine.TZLocation).Format("2006-01-02 15:04:05"), engine.dialect.URI().DBType, dstDialect.URI().DBType)) @@ -562,7 +508,7 @@ func (engine *Engine) dumpTables(ctx context.Context, tables []*schemas.Table, w colNames := engine.dialect.Quoter().Join(cols, ", ") destColNames := dstDialect.Quoter().Join(dstCols, ", ") - rows, err := engine.DB().QueryContext(engine.defaultContext, "SELECT "+colNames+" FROM "+engine.Quote(originalTableName)) + rows, err := engine.db.QueryContext(engine.defaultContext, "SELECT "+colNames+" FROM "+engine.Quote(originalTableName)) if err != nil { return err } @@ -835,28 +781,28 @@ func (engine *Engine) Cascade(trueOrFalse ...bool) *Session { } // Where method provide a condition query -func (engine *Engine) Where(query interface{}, args ...interface{}) *Session { +func (engine *Engine) Where(query any, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.Where(query, args...) } // ID method provoide a condition as (id) = ? -func (engine *Engine) ID(id interface{}) *Session { +func (engine *Engine) ID(id any) *Session { session := engine.NewSession() session.isAutoClose = true return session.ID(id) } // Before apply before Processor, affected bean is passed to closure arg -func (engine *Engine) Before(closures func(interface{})) *Session { +func (engine *Engine) Before(closures func(any)) *Session { session := engine.NewSession() session.isAutoClose = true return session.Before(closures) } // After apply after insert Processor, affected bean is passed to closure arg -func (engine *Engine) After(closures func(interface{})) *Session { +func (engine *Engine) After(closures func(any)) *Session { session := engine.NewSession() session.isAutoClose = true return session.After(closures) @@ -876,9 +822,7 @@ func (engine *Engine) StoreEngine(storeEngine string) *Session { return session.StoreEngine(storeEngine) } -// Distinct use for distinct columns. Caution: when you are using cache, -// distinct will not be cached because cache system need id, -// but distinct will not provide id +// Distinct use for distinct columns. func (engine *Engine) Distinct(columns ...string) *Session { session := engine.NewSession() session.isAutoClose = true @@ -939,42 +883,42 @@ func (engine *Engine) Nullable(columns ...string) *Session { } // In will generate "column IN (?, ?)" -func (engine *Engine) In(column string, args ...interface{}) *Session { +func (engine *Engine) In(column string, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.In(column, args...) } // NotIn will generate "column NOT IN (?, ?)" -func (engine *Engine) NotIn(column string, args ...interface{}) *Session { +func (engine *Engine) NotIn(column string, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.NotIn(column, args...) } // Incr provides a update string like "column = column + ?" -func (engine *Engine) Incr(column string, arg ...interface{}) *Session { +func (engine *Engine) Incr(column string, arg ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.Incr(column, arg...) } // Decr provides a update string like "column = column - ?" -func (engine *Engine) Decr(column string, arg ...interface{}) *Session { +func (engine *Engine) Decr(column string, arg ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.Decr(column, arg...) } // SetExpr provides a update string like "column = {expression}" -func (engine *Engine) SetExpr(column string, expression interface{}) *Session { +func (engine *Engine) SetExpr(column string, expression any) *Session { session := engine.NewSession() session.isAutoClose = true return session.SetExpr(column, expression) } // Table temporarily change the Get, Find, Update's table -func (engine *Engine) Table(tableNameOrBean interface{}) *Session { +func (engine *Engine) Table(tableNameOrBean any) *Session { session := engine.NewSession() session.isAutoClose = true return session.Table(tableNameOrBean) @@ -1013,7 +957,7 @@ func (engine *Engine) Asc(colNames ...string) *Session { } // OrderBy will generate "ORDER BY order" -func (engine *Engine) OrderBy(order interface{}, args ...interface{}) *Session { +func (engine *Engine) OrderBy(order any, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.OrderBy(order, args...) @@ -1027,7 +971,7 @@ func (engine *Engine) Prepare() *Session { } // Join the join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN -func (engine *Engine) Join(joinOperator string, tablename interface{}, condition interface{}, args ...interface{}) *Session { +func (engine *Engine) Join(joinOperator string, tablename any, condition any, args ...any) *Session { session := engine.NewSession() session.isAutoClose = true return session.Join(joinOperator, tablename, condition, args...) @@ -1053,75 +997,51 @@ func (engine *Engine) DBVersion() (*schemas.Version, error) { } // TableInfo get table info according to bean's content -func (engine *Engine) TableInfo(bean interface{}) (*schemas.Table, error) { +func (engine *Engine) TableInfo(bean any) (*schemas.Table, error) { v := utils.ReflectValue(bean) return engine.tagParser.ParseWithCache(v) } // IsTableEmpty if a table has any reocrd -func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) { +func (engine *Engine) IsTableEmpty(bean any) (bool, error) { session := engine.NewSession() defer session.Close() return session.IsTableEmpty(bean) } // IsTableExist if a table is exist -func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) { +func (engine *Engine) IsTableExist(beanOrTableName any) (bool, error) { session := engine.NewSession() defer session.Close() return session.IsTableExist(beanOrTableName) } // TableName returns table name with schema prefix if has -func (engine *Engine) TableName(bean interface{}, includeSchema ...bool) string { +func (engine *Engine) TableName(bean any, includeSchema ...bool) string { return dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean, includeSchema...) } // CreateIndexes create indexes -func (engine *Engine) CreateIndexes(bean interface{}) error { +func (engine *Engine) CreateIndexes(bean any) error { session := engine.NewSession() defer session.Close() return session.CreateIndexes(bean) } // CreateUniques create uniques -func (engine *Engine) CreateUniques(bean interface{}) error { +func (engine *Engine) CreateUniques(bean any) error { session := engine.NewSession() defer session.Close() return session.CreateUniques(bean) } -// ClearCacheBean if enabled cache, clear the cache bean -func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { - tableName := dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean) - cacher := engine.GetCacher(tableName) - if cacher != nil { - cacher.ClearIds(tableName) - cacher.DelBean(tableName, id) - } - return nil -} - -// ClearCache if enabled cache, clear some tables' cache -func (engine *Engine) ClearCache(beans ...interface{}) error { - for _, bean := range beans { - tableName := dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean) - cacher := engine.GetCacher(tableName) - if cacher != nil { - cacher.ClearIds(tableName) - cacher.ClearBeans(tableName) - } - } - return nil -} - // UnMapType remove table from tables cache func (engine *Engine) UnMapType(t reflect.Type) { engine.tagParser.ClearCacheTable(t) } // CreateTables create tabls according bean -func (engine *Engine) CreateTables(beans ...interface{}) error { +func (engine *Engine) CreateTables(beans ...any) error { session := engine.NewSession() defer session.Close() @@ -1141,7 +1061,7 @@ func (engine *Engine) CreateTables(beans ...interface{}) error { } // DropTables drop specify tables -func (engine *Engine) DropTables(beans ...interface{}) error { +func (engine *Engine) DropTables(beans ...any) error { session := engine.NewSession() defer session.Close() @@ -1161,49 +1081,49 @@ func (engine *Engine) DropTables(beans ...interface{}) error { } // DropIndexes drop indexes of a table -func (engine *Engine) DropIndexes(bean interface{}) error { +func (engine *Engine) DropIndexes(bean any) error { session := engine.NewSession() defer session.Close() return session.DropIndexes(bean) } // Exec raw sql -func (engine *Engine) Exec(sqlOrArgs ...interface{}) (sql.Result, error) { +func (engine *Engine) Exec(sqlOrArgs ...any) (sql.Result, error) { session := engine.NewSession() defer session.Close() return session.Exec(sqlOrArgs...) } // Query a raw sql and return records as []map[string][]byte -func (engine *Engine) Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error) { +func (engine *Engine) Query(sqlOrArgs ...any) (resultsSlice []map[string][]byte, err error) { session := engine.NewSession() defer session.Close() return session.Query(sqlOrArgs...) } // QueryString runs a raw sql and return records as []map[string]string -func (engine *Engine) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) { +func (engine *Engine) QueryString(sqlOrArgs ...any) ([]map[string]string, error) { session := engine.NewSession() defer session.Close() return session.QueryString(sqlOrArgs...) } -// QueryInterface runs a raw sql and return records as []map[string]interface{} -func (engine *Engine) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) { +// QueryInterface runs a raw sql and return records as []map[string]any +func (engine *Engine) QueryInterface(sqlOrArgs ...any) ([]map[string]any, error) { session := engine.NewSession() defer session.Close() return session.QueryInterface(sqlOrArgs...) } // Insert one or more records -func (engine *Engine) Insert(beans ...interface{}) (int64, error) { +func (engine *Engine) Insert(beans ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Insert(beans...) } // InsertOne insert only one record -func (engine *Engine) InsertOne(bean interface{}) (int64, error) { +func (engine *Engine) InsertOne(bean any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Insert(bean) @@ -1216,7 +1136,7 @@ func (engine *Engine) InsertOne(bean interface{}) (int64, error) { // 1.bool will defaultly be updated content nor conditions // You should call UseBool if you have bool to use. // 2.float32 & float64 may be not inexact as conditions -func (engine *Engine) Update(bean interface{}, condiBeans ...interface{}) (int64, error) { +func (engine *Engine) Update(bean any, condiBeans ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Update(bean, condiBeans...) @@ -1224,7 +1144,7 @@ func (engine *Engine) Update(bean interface{}, condiBeans ...interface{}) (int64 // Delete records, bean's non-empty fields are conditions // At least one condition must be set. -func (engine *Engine) Delete(beans ...interface{}) (int64, error) { +func (engine *Engine) Delete(beans ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Delete(beans...) @@ -1232,7 +1152,7 @@ func (engine *Engine) Delete(beans ...interface{}) (int64, error) { // Truncate records, bean's non-empty fields are conditions // In contrast to Delete this method allows deletes without conditions. -func (engine *Engine) Truncate(beans ...interface{}) (int64, error) { +func (engine *Engine) Truncate(beans ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Truncate(beans...) @@ -1240,14 +1160,14 @@ func (engine *Engine) Truncate(beans ...interface{}) (int64, error) { // Get retrieve one record from table, bean's non-empty fields // are conditions -func (engine *Engine) Get(beans ...interface{}) (bool, error) { +func (engine *Engine) Get(beans ...any) (bool, error) { session := engine.NewSession() defer session.Close() return session.Get(beans...) } // Exist returns true if the record exist otherwise return false -func (engine *Engine) Exist(bean ...interface{}) (bool, error) { +func (engine *Engine) Exist(bean ...any) (bool, error) { session := engine.NewSession() defer session.Close() return session.Exist(bean...) @@ -1256,14 +1176,14 @@ func (engine *Engine) Exist(bean ...interface{}) (bool, error) { // Find retrieve records from table, condiBeans's non-empty fields // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct -func (engine *Engine) Find(beans interface{}, condiBeans ...interface{}) error { +func (engine *Engine) Find(beans any, condiBeans ...any) error { session := engine.NewSession() defer session.Close() return session.Find(beans, condiBeans...) } // FindAndCount find the results and also return the counts -func (engine *Engine) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) { +func (engine *Engine) FindAndCount(rowsSlicePtr any, condiBean ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.FindAndCount(rowsSlicePtr, condiBean...) @@ -1271,7 +1191,7 @@ func (engine *Engine) FindAndCount(rowsSlicePtr interface{}, condiBean ...interf // Iterate record by record handle records from table, bean's non-empty fields // are conditions. -func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error { +func (engine *Engine) Iterate(bean any, fun IterFunc) error { session := engine.NewSession() defer session.Close() return session.Iterate(bean, fun) @@ -1279,41 +1199,41 @@ func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error { // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields // are conditions. -func (engine *Engine) Rows(bean interface{}) (*Rows, error) { +func (engine *Engine) Rows(bean any) (*Rows, error) { session := engine.NewSession() return session.Rows(bean) } // Count counts the records. bean's non-empty fields are conditions. -func (engine *Engine) Count(bean ...interface{}) (int64, error) { +func (engine *Engine) Count(bean ...any) (int64, error) { session := engine.NewSession() defer session.Close() return session.Count(bean...) } // Sum sum the records by some column. bean's non-empty fields are conditions. -func (engine *Engine) Sum(bean interface{}, colName string) (float64, error) { +func (engine *Engine) Sum(bean any, colName string) (float64, error) { session := engine.NewSession() defer session.Close() return session.Sum(bean, colName) } // SumInt sum the records by some column. bean's non-empty fields are conditions. -func (engine *Engine) SumInt(bean interface{}, colName string) (int64, error) { +func (engine *Engine) SumInt(bean any, colName string) (int64, error) { session := engine.NewSession() defer session.Close() return session.SumInt(bean, colName) } // Sums sum the records by some columns. bean's non-empty fields are conditions. -func (engine *Engine) Sums(bean interface{}, colNames ...string) ([]float64, error) { +func (engine *Engine) Sums(bean any, colNames ...string) ([]float64, error) { session := engine.NewSession() defer session.Close() return session.Sums(bean, colNames...) } // SumsInt like Sums but return slice of int64 instead of float64. -func (engine *Engine) SumsInt(bean interface{}, colNames ...string) ([]int64, error) { +func (engine *Engine) SumsInt(bean any, colNames ...string) ([]int64, error) { session := engine.NewSession() defer session.Close() return session.SumsInt(bean, colNames...) @@ -1334,7 +1254,7 @@ func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) { } // nowTime return current time -func (engine *Engine) nowTime(col *schemas.Column) (interface{}, time.Time, error) { +func (engine *Engine) nowTime(col *schemas.Column) (any, time.Time, error) { t := time.Now() result, err := dialects.FormatColumnTime(engine.dialect, engine.DatabaseTZ, col, t) if err != nil { @@ -1414,7 +1334,7 @@ func (engine *Engine) PingContext(ctx context.Context) error { } // Transaction Execute sql wrapped in a transaction(abbr as tx), tx will automatic commit if no errors occurred -func (engine *Engine) Transaction(f func(*Session) (interface{}, error)) (interface{}, error) { +func (engine *Engine) Transaction(f func(*Session) (any, error)) (any, error) { session := engine.NewSession() defer session.Close() diff --git a/engine_group.go b/engine_group.go index f2fe913d..b45a8441 100644 --- a/engine_group.go +++ b/engine_group.go @@ -8,11 +8,10 @@ import ( "context" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/contexts" - "xorm.io/xorm/dialects" - "xorm.io/xorm/log" - "xorm.io/xorm/names" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/names" ) // EngineGroup defines an engine group @@ -23,7 +22,7 @@ type EngineGroup struct { } // NewEngineGroup creates a new engine group -func NewEngineGroup(args1 interface{}, args2 interface{}, policies ...GroupPolicy) (*EngineGroup, error) { +func NewEngineGroup(args1 any, args2 any, policies ...GroupPolicy) (*EngineGroup, error) { var eg EngineGroup if len(policies) > 0 { eg.policy = policies[0] @@ -128,16 +127,8 @@ func (eg *EngineGroup) SetConnMaxLifetime(d time.Duration) { } } -// SetDefaultCacher set the default cacher -func (eg *EngineGroup) SetDefaultCacher(cacher caches.Cacher) { - eg.Engine.SetDefaultCacher(cacher) - for i := 0; i < len(eg.slaves); i++ { - eg.slaves[i].SetDefaultCacher(cacher) - } -} - // SetLogger set the new logger -func (eg *EngineGroup) SetLogger(logger interface{}) { +func (eg *EngineGroup) SetLogger(logger any) { eg.Engine.SetLogger(logger) for i := 0; i < len(eg.slaves); i++ { eg.slaves[i].SetLogger(logger) @@ -178,17 +169,17 @@ func (eg *EngineGroup) SetTagIdentifier(tagIdentifier string) { // SetMaxIdleConns set the max idle connections on pool, default is 2 func (eg *EngineGroup) SetMaxIdleConns(conns int) { - eg.Engine.DB().SetMaxIdleConns(conns) + eg.Engine.db.SetMaxIdleConns(conns) for i := 0; i < len(eg.slaves); i++ { - eg.slaves[i].DB().SetMaxIdleConns(conns) + eg.slaves[i].db.SetMaxIdleConns(conns) } } // SetMaxOpenConns is only available for go 1.2+ func (eg *EngineGroup) SetMaxOpenConns(conns int) { - eg.Engine.DB().SetMaxOpenConns(conns) + eg.Engine.db.SetMaxOpenConns(conns) for i := 0; i < len(eg.slaves); i++ { - eg.slaves[i].DB().SetMaxOpenConns(conns) + eg.slaves[i].db.SetMaxOpenConns(conns) } } @@ -239,28 +230,28 @@ func (eg *EngineGroup) Slaves() []*Engine { } // Query execcute a select SQL and return the result -func (eg *EngineGroup) Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error) { +func (eg *EngineGroup) Query(sqlOrArgs ...any) (resultsSlice []map[string][]byte, err error) { sess := eg.NewSession() sess.isAutoClose = true return sess.Query(sqlOrArgs...) } // QueryInterface execcute a select SQL and return the result -func (eg *EngineGroup) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) { +func (eg *EngineGroup) QueryInterface(sqlOrArgs ...any) ([]map[string]any, error) { sess := eg.NewSession() sess.isAutoClose = true return sess.QueryInterface(sqlOrArgs...) } // QueryString execcute a select SQL and return the result -func (eg *EngineGroup) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) { +func (eg *EngineGroup) QueryString(sqlOrArgs ...any) ([]map[string]string, error) { sess := eg.NewSession() sess.isAutoClose = true return sess.QueryString(sqlOrArgs...) } // Rows execcute a select SQL and return the result -func (eg *EngineGroup) Rows(bean interface{}) (*Rows, error) { +func (eg *EngineGroup) Rows(bean any) (*Rows, error) { sess := eg.NewSession() sess.isAutoClose = true return sess.Rows(bean) diff --git a/engine_group_policy.go b/engine_group_policy.go index 1def8ce4..45028862 100644 --- a/engine_group_policy.go +++ b/engine_group_policy.go @@ -25,7 +25,7 @@ func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine { // RandomPolicy implmentes randomly chose the slave of slaves func RandomPolicy() GroupPolicyHandler { - var r = rand.New(rand.NewSource(time.Now().UnixNano())) + r := rand.New(rand.NewSource(time.Now().UnixNano())) return func(g *EngineGroup) *Engine { return g.Slaves()[r.Intn(len(g.Slaves()))] } @@ -33,16 +33,16 @@ func RandomPolicy() GroupPolicyHandler { // WeightRandomPolicy implmentes randomly chose the slave of slaves func WeightRandomPolicy(weights []int) GroupPolicyHandler { - var rands = make([]int, 0, len(weights)) + rands := make([]int, 0, len(weights)) for i := 0; i < len(weights); i++ { for n := 0; n < weights[i]; n++ { rands = append(rands, i) } } - var r = rand.New(rand.NewSource(time.Now().UnixNano())) + r := rand.New(rand.NewSource(time.Now().UnixNano())) return func(g *EngineGroup) *Engine { - var slaves = g.Slaves() + slaves := g.Slaves() idx := rands[r.Intn(len(rands))] if idx >= len(slaves) { idx = len(slaves) - 1 @@ -53,10 +53,10 @@ func WeightRandomPolicy(weights []int) GroupPolicyHandler { // RoundRobinPolicy returns a group policy handler func RoundRobinPolicy() GroupPolicyHandler { - var pos = -1 + pos := -1 var lock sync.Mutex return func(g *EngineGroup) *Engine { - var slaves = g.Slaves() + slaves := g.Slaves() lock.Lock() defer lock.Unlock() @@ -71,17 +71,17 @@ func RoundRobinPolicy() GroupPolicyHandler { // WeightRoundRobinPolicy returns a group policy handler func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler { - var rands = make([]int, 0, len(weights)) + rands := make([]int, 0, len(weights)) for i := 0; i < len(weights); i++ { for n := 0; n < weights[i]; n++ { rands = append(rands, i) } } - var pos = -1 + pos := -1 var lock sync.Mutex return func(g *EngineGroup) *Engine { - var slaves = g.Slaves() + slaves := g.Slaves() lock.Lock() defer lock.Unlock() pos++ @@ -100,11 +100,11 @@ func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler { // LeastConnPolicy implements GroupPolicy, every time will get the least connections slave func LeastConnPolicy() GroupPolicyHandler { return func(g *EngineGroup) *Engine { - var slaves = g.Slaves() + slaves := g.Slaves() connections := 0 idx := 0 for i := 0; i < len(slaves); i++ { - openConnections := slaves[i].DB().Stats().OpenConnections + openConnections := slaves[i].db.Stats().OpenConnections if i == 0 { connections = openConnections idx = i diff --git a/error.go b/error.go index cfa5c819..d171c94a 100644 --- a/error.go +++ b/error.go @@ -9,18 +9,14 @@ import ( ) var ( - // ErrPtrSliceType represents a type error - ErrPtrSliceType = errors.New("A point to a slice is needed") + // ErrParamsType params error ErrParamsType = errors.New("Params type error") // ErrTableNotFound table not found error ErrTableNotFound = errors.New("Table not found") // ErrUnSupportedType unsupported error ErrUnSupportedType = errors.New("Unsupported type error") - // ErrNotExist record does not exist error - ErrNotExist = errors.New("Record does not exist") - // ErrCacheFailed cache failed error - ErrCacheFailed = errors.New("Cache failed") + // ErrConditionType condition type unsupported ErrConditionType = errors.New("Unsupported condition type") ) diff --git a/session_find.go b/find.go similarity index 55% rename from session_find.go rename to find.go index 1026910c..945aa0dc 100644 --- a/session_find.go +++ b/find.go @@ -11,11 +11,10 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/caches" - "xorm.io/xorm/convert" - "xorm.io/xorm/internal/statements" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) const ( @@ -26,7 +25,7 @@ const ( // Find retrieve records from table, condiBeans's non-empty fields // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct -func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) error { +func (session *Session) Find(rowsSlicePtr any, condiBean ...any) error { if session.isAutoClose { defer session.Close() } @@ -34,7 +33,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) } // FindAndCount find the results and also return the counts -func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...interface{}) (int64, error) { +func (session *Session) FindAndCount(rowsSlicePtr any, condiBean ...any) (int64, error) { if session.isAutoClose { defer session.Close() } @@ -78,7 +77,7 @@ func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...inte return session.Unscoped().Count() } -func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) error { +func (session *Session) find(rowsSlicePtr any, condiBean ...any) error { defer session.resetStatement() if session.statement.LastError != nil { return session.statement.LastError @@ -148,18 +147,6 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) return err } - if session.statement.ColumnMap.IsEmpty() && session.canCache() { - if cacher := session.engine.GetCacher(session.statement.TableName()); cacher != nil && - !session.statement.IsDistinct && - !session.statement.GetUnscoped() { - err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...) - if err != ErrCacheFailed { - return err - } - session.engine.logger.Warnf("Cache Find Failed") - } - } - return session.noCacheFind(table, sliceValue, sqlStr, args...) } @@ -221,7 +208,7 @@ func ParseColumnsSchema(fieldNames []string, types []*sql.ColumnType, table *sch return &columnsSchema } -func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error { +func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect.Value, sqlStr string, args ...any) error { elemType := containerValue.Type().Elem() var isPointer bool if elemType.Kind() == reflect.Ptr { @@ -331,216 +318,3 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect } return rows.Err() } - -func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr interface{}, args ...interface{}) (err error) { - if !session.canCache() || - utils.IndexNoCase(sqlStr, "having") != -1 || - utils.IndexNoCase(sqlStr, "group by") != -1 { - return ErrCacheFailed - } - - tableName := session.statement.TableName() - cacher := session.engine.cacherMgr.GetCacher(tableName) - if cacher == nil { - return nil - } - - for _, filter := range session.engine.dialect.Filters() { - sqlStr = filter.Do(session.ctx, sqlStr) - } - - newsql := session.statement.ConvertIDSQL(sqlStr) - if newsql == "" { - return ErrCacheFailed - } - - table := session.statement.RefTable - ids, err := caches.GetCacheSql(cacher, tableName, newsql, args) - if err != nil { - rows, err := session.queryRows(newsql, args...) - if err != nil { - return err - } - defer rows.Close() - - var i int - ids = make([]schemas.PK, 0) - for rows.Next() { - i++ - if i > 500 { - session.engine.logger.Debugf("[cacheFind] ids length > 500, no cache") - return ErrCacheFailed - } - res := make([]string, len(table.PrimaryKeys)) - err = rows.ScanSlice(&res) - if err != nil { - return err - } - var pk schemas.PK = make([]interface{}, len(table.PrimaryKeys)) - for i, col := range table.PKColumns() { - pk[i], err = col.ConvertID(res[i]) - if err != nil { - return err - } - } - - ids = append(ids, pk) - } - if rows.Err() != nil { - return rows.Err() - } - - session.engine.logger.Debugf("[cache] cache sql: %v, %v, %v, %v, %v", ids, tableName, sqlStr, newsql, args) - err = caches.PutCacheSql(cacher, ids, tableName, newsql, args) - if err != nil { - return err - } - } else { - session.engine.logger.Debugf("[cache] cache hit sql: %v, %v, %v, %v", tableName, sqlStr, newsql, args) - } - - sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) - - ididxes := make(map[string]int) - var ides []schemas.PK - temps := make([]interface{}, len(ids)) - - for idx, id := range ids { - sid, err := id.ToString() - if err != nil { - return err - } - bean := cacher.GetBean(tableName, sid) - - // fix issue #894 - isHit := func() (ht bool) { - if bean == nil { - ht = false - return - } - ckb := reflect.ValueOf(bean).Elem().Type() - ht = ckb == t - if !ht && t.Kind() == reflect.Ptr { - ht = t.Elem() == ckb - } - return - } - if !isHit() { - ides = append(ides, id) - ididxes[sid] = idx - } else { - session.engine.logger.Debugf("[cache] cache hit bean: %v, %v, %v", tableName, id, bean) - - pk, err := table.IDOfV(reflect.ValueOf(bean)) - if err != nil { - return err - } - - xid, err := pk.ToString() - if err != nil { - return err - } - - if sid != xid { - session.engine.logger.Errorf("[cache] error cache: %v, %v, %v", xid, sid, bean) - return ErrCacheFailed - } - temps[idx] = bean - } - } - - if len(ides) > 0 { - slices := reflect.New(reflect.SliceOf(t)) - beans := slices.Interface() - - statement := session.statement - session.statement = statements.NewStatement( - session.engine.dialect, - session.engine.tagParser, - session.engine.DatabaseTZ, - ) - if len(table.PrimaryKeys) == 1 { - ff := make([]interface{}, 0, len(ides)) - for _, ie := range ides { - ff = append(ff, ie[0]) - } - - session.In("`"+table.PrimaryKeys[0]+"`", ff...) - } else { - for _, ie := range ides { - cond := builder.NewCond() - for i, name := range table.PrimaryKeys { - cond = cond.And(builder.Eq{"`" + name + "`": ie[i]}) - } - session.Or(cond) - } - } - - err = session.NoCache().Table(tableName).find(beans) - if err != nil { - return err - } - session.statement = statement - - vs := reflect.Indirect(reflect.ValueOf(beans)) - for i := 0; i < vs.Len(); i++ { - rv := vs.Index(i) - if rv.Kind() != reflect.Ptr { - rv = rv.Addr() - } - id, err := table.IDOfV(rv) - if err != nil { - return err - } - sid, err := id.ToString() - if err != nil { - return err - } - - bean := rv.Interface() - temps[ididxes[sid]] = bean - session.engine.logger.Debugf("[cache] cache bean: %v, %v, %v, %v", tableName, id, bean, temps) - cacher.PutBean(tableName, sid, bean) - } - } - - for j := 0; j < len(temps); j++ { - bean := temps[j] - if bean == nil { - session.engine.logger.Warnf("[cache] cache no hit: %v, %v, %v", tableName, ids[j], temps) - // return errors.New("cache error") // !nashtsai! no need to return error, but continue instead - continue - } - if sliceValue.Kind() == reflect.Slice { - if t.Kind() == reflect.Ptr { - sliceValue.Set(reflect.Append(sliceValue, reflect.ValueOf(bean))) - } else { - sliceValue.Set(reflect.Append(sliceValue, reflect.Indirect(reflect.ValueOf(bean)))) - } - } else if sliceValue.Kind() == reflect.Map { - key := ids[j] - keyType := sliceValue.Type().Key() - keyValue := reflect.New(keyType) - var ikey interface{} - if len(key) == 1 { - if err := convert.AssignValue(keyValue, key[0]); err != nil { - return err - } - ikey = keyValue.Elem().Interface() - } else { - if keyType.Kind() != reflect.Slice { - return errors.New("table have multiple primary keys, key is not schemas.PK or slice") - } - ikey = key - } - - if t.Kind() == reflect.Ptr { - sliceValue.SetMapIndex(reflect.ValueOf(ikey), reflect.ValueOf(bean)) - } else { - sliceValue.SetMapIndex(reflect.ValueOf(ikey), reflect.Indirect(reflect.ValueOf(bean))) - } - } - } - - return nil -} diff --git a/session_get.go b/get.go similarity index 58% rename from session_get.go rename to get.go index 0d590330..a1bf7e8b 100644 --- a/session_get.go +++ b/get.go @@ -10,31 +10,27 @@ import ( "fmt" "math/big" "reflect" - "strconv" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/convert" - "xorm.io/xorm/core" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) -var ( - // ErrObjectIsNil return error of object is nil - ErrObjectIsNil = errors.New("object should not be nil") -) +// ErrObjectIsNil return error of object is nil +var ErrObjectIsNil = errors.New("object should not be nil") // Get retrieve one record from database, bean's non-empty fields // will be as conditions -func (session *Session) Get(beans ...interface{}) (bool, error) { +func (session *Session) Get(beans ...any) (bool, error) { if session.isAutoClose { defer session.Close() } return session.get(beans...) } -func isPtrOfTime(v interface{}) bool { +func isPtrOfTime(v any) bool { if _, ok := v.(*time.Time); ok { return true } @@ -47,7 +43,7 @@ func isPtrOfTime(v interface{}) bool { return el.Type().ConvertibleTo(schemas.TimeType) } -func (session *Session) get(beans ...interface{}) (bool, error) { +func (session *Session) get(beans ...any) (bool, error) { defer session.resetStatement() if session.statement.LastError != nil { @@ -66,7 +62,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) { return false, ErrObjectIsNil } - var isStruct = beanValue.Elem().Kind() == reflect.Struct && !isPtrOfTime(beans[0]) + isStruct := beanValue.Elem().Kind() == reflect.Struct && !isPtrOfTime(beans[0]) if isStruct { if err := session.statement.SetRefBean(beans[0]); err != nil { return false, err @@ -74,7 +70,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) { } var sqlStr string - var args []interface{} + var args []any var err error if session.statement.RawSQL == "" { @@ -92,17 +88,6 @@ func (session *Session) get(beans ...interface{}) (bool, error) { } table := session.statement.RefTable - - if session.statement.ColumnMap.IsEmpty() && session.canCache() && isStruct { - if cacher := session.engine.GetCacher(session.statement.TableName()); cacher != nil && - !session.statement.GetUnscoped() { - has, err := session.cacheGet(beans[0], sqlStr, args...) - if err != ErrCacheFailed { - return has, err - } - } - } - context := session.statement.Context if context != nil && isStruct { res := context.Get(fmt.Sprintf("%v-%v", sqlStr, args)) @@ -129,7 +114,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) { return true, nil } -func isScannableStruct(bean interface{}, typeLen int) bool { +func isScannableStruct(bean any, typeLen int) bool { switch bean.(type) { case *time.Time: return false @@ -143,7 +128,7 @@ func isScannableStruct(bean interface{}, typeLen int) bool { return true } -func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table, beans []interface{}, sqlStr string, args ...interface{}) (bool, error) { +func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table, beans []any, sqlStr string, args ...any) (bool, error) { rows, err := session.queryRows(sqlStr, args...) if err != nil { return false, err @@ -174,7 +159,7 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table, return true, session.executeProcessors() } -func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKind reflect.Kind, beans []interface{}, columnsSchema *ColumnsSchema, types []*sql.ColumnType, fields []string) error { +func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKind reflect.Kind, beans []any, columnsSchema *ColumnsSchema, types []*sql.ColumnType, fields []string) error { if len(beans) == 1 { bean := beans[0] switch firstBeanKind { @@ -204,7 +189,7 @@ func (session *Session) scan(rows *core.Rows, table *schemas.Table, firstBeanKin return session.engine.scan(rows, fields, types, beans...) } -func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, fields []string, bean interface{}) error { +func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, fields []string, bean any) error { switch t := bean.(type) { case *[]string: res, err := session.engine.scanStringInterface(rows, fields, types) @@ -212,7 +197,7 @@ func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, field return err } - var needAppend = len(*t) == 0 // both support slice is empty or has been initlized + needAppend := len(*t) == 0 // both support slice is empty or has been initlized for i, r := range res { if needAppend { *t = append(*t, r.(*sql.NullString).String) @@ -221,12 +206,12 @@ func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, field } } return nil - case *[]interface{}: + case *[]any: scanResults, err := session.engine.scanInterfaces(rows, fields, types) if err != nil { return err } - var needAppend = len(*t) == 0 + needAppend := len(*t) == 0 for ii := range fields { s, err := convert.Interface2Interface(session.engine.DatabaseTZ, scanResults[ii]) if err != nil { @@ -244,7 +229,7 @@ func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, field } } -func (session *Session) getMap(rows *core.Rows, types []*sql.ColumnType, fields []string, bean interface{}) error { +func (session *Session) getMap(rows *core.Rows, types []*sql.ColumnType, fields []string, bean any) error { switch t := bean.(type) { case *map[string]string: scanResults, err := session.engine.scanStringInterface(rows, fields, types) @@ -255,7 +240,7 @@ func (session *Session) getMap(rows *core.Rows, types []*sql.ColumnType, fields (*t)[key] = scanResults[ii].(*sql.NullString).String } return nil - case *map[string]interface{}: + case *map[string]any: scanResults, err := session.engine.scanInterfaces(rows, fields, types) if err != nil { return err @@ -273,96 +258,29 @@ func (session *Session) getMap(rows *core.Rows, types []*sql.ColumnType, fields } } -func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interface{}) (has bool, err error) { - // if has no reftable, then don't use cache currently - if !session.canCache() { - return false, ErrCacheFailed +// Exist returns true if the record exist otherwise return false +func (session *Session) Exist(bean ...any) (bool, error) { + if session.isAutoClose { + defer session.Close() } - for _, filter := range session.engine.dialect.Filters() { - sqlStr = filter.Do(session.ctx, sqlStr) - } - newsql := session.statement.ConvertIDSQL(sqlStr) - if newsql == "" { - return false, ErrCacheFailed + if session.statement.LastError != nil { + return false, session.statement.LastError } - tableName := session.statement.TableName() - cacher := session.engine.cacherMgr.GetCacher(tableName) - - session.engine.logger.Debugf("[cache] Get SQL: %s, %v", newsql, args) - table := session.statement.RefTable - ids, err := caches.GetCacheSql(cacher, tableName, newsql, args) + sqlStr, args, err := session.statement.GenExistSQL(bean...) if err != nil { - var res = make([]string, len(table.PrimaryKeys)) - rows, err := session.NoCache().queryRows(newsql, args...) - if err != nil { - return false, err - } - defer rows.Close() - - if rows.Next() { - err = rows.ScanSlice(&res) - if err != nil { - return true, err - } - } else { - if rows.Err() != nil { - return false, rows.Err() - } - return false, ErrCacheFailed - } - - var pk schemas.PK = make([]interface{}, len(table.PrimaryKeys)) - for i, col := range table.PKColumns() { - if col.SQLType.IsText() { - pk[i] = res[i] - } else if col.SQLType.IsNumeric() { - n, err := strconv.ParseInt(res[i], 10, 64) - if err != nil { - return false, err - } - pk[i] = n - } else { - return false, errors.New("unsupported") - } - } - - ids = []schemas.PK{pk} - session.engine.logger.Debugf("[cache] cache ids: %s, %v", newsql, ids) - err = caches.PutCacheSql(cacher, ids, tableName, newsql, args) - if err != nil { - return false, err - } - } else { - session.engine.logger.Debugf("[cache] cache hit: %s, %v", newsql, ids) + return false, err } - if len(ids) > 0 { - structValue := reflect.Indirect(reflect.ValueOf(bean)) - id := ids[0] - session.engine.logger.Debugf("[cache] get bean: %s, %v", tableName, id) - sid, err := id.ToString() - if err != nil { - return false, err - } - cacheBean := cacher.GetBean(tableName, sid) - if cacheBean == nil { - cacheBean = bean - has, err = session.nocacheGet(reflect.Struct, table, []interface{}{cacheBean}, sqlStr, args...) - if err != nil || !has { - return has, err - } - - session.engine.logger.Debugf("[cache] cache bean: %s, %v, %v", tableName, id, cacheBean) - cacher.PutBean(tableName, sid, cacheBean) - } else { - session.engine.logger.Debugf("[cache] cache hit: %s, %v, %v", tableName, id, cacheBean) - has = true - } - structValue.Set(reflect.Indirect(reflect.ValueOf(cacheBean))) - - return has, nil + rows, err := session.queryRows(sqlStr, args...) + if err != nil { + return false, err } - return false, nil + defer rows.Close() + + if rows.Next() { + return true, nil + } + return false, rows.Err() } diff --git a/go.mod b/go.mod index b48b3bbc..c6665677 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,12 @@ -module xorm.io/xorm +module xorm.io/xorm/v2 -go 1.16 +go 1.20 require ( gitee.com/travelliu/dm v1.8.11192 github.com/denisenkom/go-mssqldb v0.12.3 github.com/go-sql-driver/mysql v1.7.0 github.com/goccy/go-json v0.8.1 - github.com/golang/snappy v0.0.4 // indirect github.com/jackc/pgx/v4 v4.18.0 github.com/json-iterator/go v1.1.12 github.com/lib/pq v1.10.7 @@ -15,7 +14,44 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/stretchr/testify v1.8.1 github.com/syndtr/goleveldb v1.0.0 - github.com/ziutek/mymysql v1.5.4 modernc.org/sqlite v1.20.4 xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 + xorm.io/xorm v1.3.4 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + golang.org/x/tools v0.1.12 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.22.2 // indirect + modernc.org/mathutil v1.5.0 // indirect + modernc.org/memory v1.4.0 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5c780ec6..34b58593 100644 --- a/go.sum +++ b/go.sum @@ -55,7 +55,6 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -76,7 +75,6 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -181,7 +179,6 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -343,3 +340,5 @@ modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ= xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM= xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI= +xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo= diff --git a/session_insert.go b/insert.go similarity index 87% rename from session_insert.go rename to insert.go index 7cc15241..f62f326d 100644 --- a/session_insert.go +++ b/insert.go @@ -13,17 +13,20 @@ import ( "time" "xorm.io/builder" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) // ErrNoElementsOnSlice represents an error there is no element when insert var ErrNoElementsOnSlice = errors.New("no element on slice when insert") +// ErrPtrSliceType represents a type error +var ErrPtrSliceType = errors.New("a point to a slice is needed") + // Insert insert one or more beans -func (session *Session) Insert(beans ...interface{}) (int64, error) { +func (session *Session) Insert(beans ...any) (int64, error) { var affected int64 var err error @@ -41,9 +44,9 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) { var cnt int64 var err error switch v := bean.(type) { - case map[string]interface{}: + case map[string]any: cnt, err = session.insertMapInterface(v) - case []map[string]interface{}: + case []map[string]any: cnt, err = session.insertMultipleMapInterface(v) case map[string]string: cnt, err = session.insertMapString(v) @@ -66,7 +69,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) { return affected, err } -func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, error) { +func (session *Session) insertMultipleStruct(rowsSlicePtr any) (int64, error) { sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) if sliceValue.Kind() != reflect.Slice { return 0, errors.New("needs a pointer to a slice") @@ -90,7 +93,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e size = sliceValue.Len() colNames []string colMultiPlaces []string - args []interface{} + args []any ) for i := 0; i < size; i++ { @@ -111,7 +114,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e closure(elemValue) } - if processor, ok := interface{}(elemValue).(BeforeInsertProcessor); ok { + if processor, ok := any(elemValue).(BeforeInsertProcessor); ok { processor.BeforeInsert() } // -- @@ -158,14 +161,14 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e args = append(args, val) colName := col.Name - session.afterClosures = append(session.afterClosures, func(bean interface{}) { + session.afterClosures = append(session.afterClosures, func(bean any) { col := table.GetColumn(colName) setColumnTime(bean, col, t) }) } else if col.IsVersion && session.statement.CheckVersion { args = append(args, 1) colName := col.Name - session.afterClosures = append(session.afterClosures, func(bean interface{}) { + session.afterClosures = append(session.afterClosures, func(bean any) { col := table.GetColumn(colName) setColumnInt(bean, col, 1) }) @@ -197,8 +200,6 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e return 0, err } - _ = session.cacheInsert(tableName) - lenAfterClosures := len(session.afterClosures) for i := 0; i < size; i++ { elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().Interface() @@ -217,7 +218,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e if value, has := session.afterInsertBeans[elemValue]; has && value != nil { *value = append(*value, session.afterClosures...) } else { - afterClosures := make([]func(interface{}), lenAfterClosures) + afterClosures := make([]func(any), lenAfterClosures) copy(afterClosures, session.afterClosures) session.afterInsertBeans[elemValue] = &afterClosures } @@ -234,7 +235,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e } // InsertMulti insert multiple records -func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) { +func (session *Session) InsertMulti(rowsSlicePtr any) (int64, error) { if session.isAutoClose { defer session.Close() } @@ -247,7 +248,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) { return session.insertMultipleStruct(rowsSlicePtr) } -func (session *Session) insertStruct(bean interface{}) (int64, error) { +func (session *Session) insertStruct(bean any) (int64, error) { if err := session.statement.SetRefBean(bean); err != nil { return 0, err } @@ -261,7 +262,7 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { } cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used - if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok { + if processor, ok := any(bean).(BeforeInsertProcessor); ok { processor.BeforeInsert() } @@ -279,12 +280,12 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { } sqlStr = session.engine.dialect.Quoter().Replace(sqlStr) - handleAfterInsertProcessorFunc := func(bean interface{}) { + handleAfterInsertProcessorFunc := func(bean any) { if session.isAutoCommit { for _, closure := range session.afterClosures { closure(bean) } - if processor, ok := interface{}(bean).(AfterInsertProcessor); ok { + if processor, ok := any(bean).(AfterInsertProcessor); ok { processor.AfterInsert() } } else { @@ -293,12 +294,12 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { if value, has := session.afterInsertBeans[bean]; has && value != nil { *value = append(*value, session.afterClosures...) } else { - afterClosures := make([]func(interface{}), lenAfterClosures) + afterClosures := make([]func(any), lenAfterClosures) copy(afterClosures, session.afterClosures) session.afterInsertBeans[bean] = &afterClosures } } else { - if _, ok := interface{}(bean).(AfterInsertProcessor); ok { + if _, ok := any(bean).(AfterInsertProcessor); ok { session.afterInsertBeans[bean] = nil } } @@ -309,7 +310,7 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { // if there is auto increment column and driver don't support return it if len(table.AutoIncrement) > 0 && !session.engine.driver.Features().SupportReturnInsertedID { var sql string - var newArgs []interface{} + var newArgs []any var needCommit bool var id int64 if session.engine.dialect.URI().DBType == schemas.ORACLE || session.engine.dialect.URI().DBType == schemas.DAMENG { @@ -354,8 +355,6 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { defer handleAfterInsertProcessorFunc(bean) - _ = session.cacheInsert(tableName) - if table.Version != "" && session.statement.CheckVersion { verValue, err := table.VersionColumn().ValueOf(bean) if err != nil { @@ -384,8 +383,6 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { defer handleAfterInsertProcessorFunc(bean) - _ = session.cacheInsert(tableName) - if table.Version != "" && session.statement.CheckVersion { verValue, err := table.VersionColumn().ValueOf(bean) if err != nil { @@ -425,7 +422,7 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) { // The in parameter bean must a struct or a point to struct. The return // parameter is inserted and error // Deprecated: Please use Insert directly -func (session *Session) InsertOne(bean interface{}) (int64, error) { +func (session *Session) InsertOne(bean any) (int64, error) { if session.isAutoClose { defer session.Close() } @@ -433,24 +430,11 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) { return session.insertStruct(bean) } -func (session *Session) cacheInsert(table string) error { - if !session.statement.UseCache { - return nil - } - cacher := session.engine.cacherMgr.GetCacher(table) - if cacher == nil { - return nil - } - session.engine.logger.Debugf("[cache] clear SQL: %v", table) - cacher.ClearIds(table) - return nil -} - // genInsertColumns generates insert needed columns -func (session *Session) genInsertColumns(bean interface{}) ([]string, []interface{}, error) { +func (session *Session) genInsertColumns(bean any) ([]string, []any, error) { table := session.statement.RefTable colNames := make([]string, 0, len(table.ColumnsSeq())) - args := make([]interface{}, 0, len(table.ColumnsSeq())) + args := make([]any, 0, len(table.ColumnsSeq())) for _, col := range table.Columns() { if col.MapType == schemas.ONLYFROMDB { @@ -508,7 +492,7 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac args = append(args, val) colName := col.Name - session.afterClosures = append(session.afterClosures, func(bean interface{}) { + session.afterClosures = append(session.afterClosures, func(bean any) { col := table.GetColumn(colName) setColumnTime(bean, col, t) }) @@ -527,7 +511,7 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac return colNames, args, nil } -func (session *Session) insertMapInterface(m map[string]interface{}) (int64, error) { +func (session *Session) insertMapInterface(m map[string]any) (int64, error) { if len(m) == 0 { return 0, ErrParamsType } @@ -546,7 +530,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err } sort.Strings(columns) - args := make([]interface{}, 0, len(m)) + args := make([]any, 0, len(m)) for _, colName := range columns { args = append(args, m[colName]) } @@ -554,7 +538,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err return session.insertMap(columns, args) } -func (session *Session) insertMultipleMapInterface(maps []map[string]interface{}) (int64, error) { +func (session *Session) insertMultipleMapInterface(maps []map[string]any) (int64, error) { if len(maps) == 0 { return 0, ErrNoElementsOnSlice } @@ -573,9 +557,9 @@ func (session *Session) insertMultipleMapInterface(maps []map[string]interface{} } sort.Strings(columns) - argss := make([][]interface{}, 0, len(maps)) + argss := make([][]any, 0, len(maps)) for _, m := range maps { - args := make([]interface{}, 0, len(m)) + args := make([]any, 0, len(m)) for _, colName := range columns { args = append(args, m[colName]) } @@ -605,7 +589,7 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) { sort.Strings(columns) - args := make([]interface{}, 0, len(m)) + args := make([]any, 0, len(m)) for _, colName := range columns { args = append(args, m[colName]) } @@ -632,9 +616,9 @@ func (session *Session) insertMultipleMapString(maps []map[string]string) (int64 } sort.Strings(columns) - argss := make([][]interface{}, 0, len(maps)) + argss := make([][]any, 0, len(maps)) for _, m := range maps { - args := make([]interface{}, 0, len(m)) + args := make([]any, 0, len(m)) for _, colName := range columns { args = append(args, m[colName]) } @@ -644,7 +628,7 @@ func (session *Session) insertMultipleMapString(maps []map[string]string) (int64 return session.insertMultipleMap(columns, argss) } -func (session *Session) insertMap(columns []string, args []interface{}) (int64, error) { +func (session *Session) insertMap(columns []string, args []any) (int64, error) { tableName := session.statement.TableName() if len(tableName) == 0 { return 0, ErrTableNotFound @@ -656,10 +640,6 @@ func (session *Session) insertMap(columns []string, args []interface{}) (int64, } sql = session.engine.dialect.Quoter().Replace(sql) - if err := session.cacheInsert(tableName); err != nil { - return 0, err - } - res, err := session.exec(sql, args...) if err != nil { return 0, err @@ -671,7 +651,7 @@ func (session *Session) insertMap(columns []string, args []interface{}) (int64, return affected, nil } -func (session *Session) insertMultipleMap(columns []string, argss [][]interface{}) (int64, error) { +func (session *Session) insertMultipleMap(columns []string, argss [][]any) (int64, error) { tableName := session.statement.TableName() if len(tableName) == 0 { return 0, ErrTableNotFound @@ -683,10 +663,6 @@ func (session *Session) insertMultipleMap(columns []string, argss [][]interface{ } sql = session.engine.dialect.Quoter().Replace(sql) - if err := session.cacheInsert(tableName); err != nil { - return 0, err - } - res, err := session.exec(sql, args...) if err != nil { return 0, err diff --git a/interface.go b/interface.go index 03dfd236..995aada9 100644 --- a/interface.go +++ b/interface.go @@ -10,12 +10,11 @@ import ( "reflect" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/contexts" - "xorm.io/xorm/dialects" - "xorm.io/xorm/log" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" ) // Interface defines the interface which Engine, EngineGroup and Session will implementate. @@ -25,89 +24,83 @@ type Interface interface { Asc(colNames ...string) *Session BufferSize(size int) *Session Cols(columns ...string) *Session - Count(...interface{}) (int64, error) - CreateIndexes(bean interface{}) error - CreateUniques(bean interface{}) error - Decr(column string, arg ...interface{}) *Session + Count(...any) (int64, error) + CreateIndexes(bean any) error + CreateUniques(bean any) error + Decr(column string, arg ...any) *Session Desc(...string) *Session - Delete(...interface{}) (int64, error) - Truncate(...interface{}) (int64, error) + Delete(...any) (int64, error) + Truncate(...any) (int64, error) Distinct(columns ...string) *Session - DropIndexes(bean interface{}) error - Exec(sqlOrArgs ...interface{}) (sql.Result, error) - Exist(bean ...interface{}) (bool, error) - Find(interface{}, ...interface{}) error - FindAndCount(interface{}, ...interface{}) (int64, error) - Get(...interface{}) (bool, error) + DropIndexes(bean any) error + Exec(sqlOrArgs ...any) (sql.Result, error) + Exist(bean ...any) (bool, error) + Find(any, ...any) error + FindAndCount(any, ...any) (int64, error) + Get(...any) (bool, error) GroupBy(keys string) *Session - ID(interface{}) *Session - In(string, ...interface{}) *Session - Incr(column string, arg ...interface{}) *Session - Insert(...interface{}) (int64, error) - InsertOne(interface{}) (int64, error) - IsTableEmpty(bean interface{}) (bool, error) - IsTableExist(beanOrTableName interface{}) (bool, error) - Iterate(interface{}, IterFunc) error + ID(any) *Session + In(string, ...any) *Session + Incr(column string, arg ...any) *Session + Insert(...any) (int64, error) + InsertOne(any) (int64, error) + IsTableEmpty(bean any) (bool, error) + IsTableExist(beanOrTableName any) (bool, error) + Iterate(any, IterFunc) error Limit(int, ...int) *Session MustCols(columns ...string) *Session NoAutoCondition(...bool) *Session - NotIn(string, ...interface{}) *Session + NotIn(string, ...any) *Session Nullable(...string) *Session - Join(joinOperator string, tablename interface{}, condition interface{}, args ...interface{}) *Session + Join(joinOperator string, tablename any, condition any, args ...any) *Session Omit(columns ...string) *Session - OrderBy(order interface{}, args ...interface{}) *Session + OrderBy(order any, args ...any) *Session Ping() error - Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error) - QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) - QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) - Rows(bean interface{}) (*Rows, error) - SetExpr(string, interface{}) *Session + Query(sqlOrArgs ...any) (resultsSlice []map[string][]byte, err error) + QueryInterface(sqlOrArgs ...any) ([]map[string]any, error) + QueryString(sqlOrArgs ...any) ([]map[string]string, error) + Rows(bean any) (*Rows, error) + SetExpr(string, any) *Session Select(string) *Session - SQL(interface{}, ...interface{}) *Session - Sum(bean interface{}, colName string) (float64, error) - SumInt(bean interface{}, colName string) (int64, error) - Sums(bean interface{}, colNames ...string) ([]float64, error) - SumsInt(bean interface{}, colNames ...string) ([]int64, error) - Table(tableNameOrBean interface{}) *Session + SQL(any, ...any) *Session + Sum(bean any, colName string) (float64, error) + SumInt(bean any, colName string) (int64, error) + Sums(bean any, colNames ...string) ([]float64, error) + SumsInt(bean any, colNames ...string) ([]int64, error) + Table(tableNameOrBean any) *Session Unscoped() *Session - Update(bean interface{}, condiBeans ...interface{}) (int64, error) + Update(bean any, condiBeans ...any) (int64, error) UseBool(...string) *Session - Where(interface{}, ...interface{}) *Session + Where(any, ...any) *Session } // EngineInterface defines the interface which Engine, EngineGroup will implementate. type EngineInterface interface { Interface - Before(func(interface{})) *Session + Before(func(any)) *Session Charset(charset string) *Session - ClearCache(...interface{}) error Context(context.Context) *Session - CreateTables(...interface{}) error + CreateTables(...any) error DBMetas() ([]*schemas.Table, error) DBVersion() (*schemas.Version, error) Dialect() dialects.Dialect DriverName() string - DropTables(...interface{}) error + DropTables(...any) error DumpAllToFile(fp string, tp ...schemas.DBType) error - GetCacher(string) caches.Cacher GetColumnMapper() names.Mapper - GetDefaultCacher() caches.Cacher GetTableMapper() names.Mapper GetTZDatabase() *time.Location GetTZLocation() *time.Location ImportFile(fp string) ([]sql.Result, error) - MapCacher(interface{}, caches.Cacher) error NewSession() *Session NoAutoTime() *Session Prepare() *Session Quote(string) string - SetCacher(string, caches.Cacher) SetConnMaxLifetime(time.Duration) SetColumnMapper(names.Mapper) SetTagIdentifier(string) - SetDefaultCacher(caches.Cacher) - SetLogger(logger interface{}) + SetLogger(logger any) SetLogLevel(log.LogLevel) SetMapper(names.Mapper) SetMaxOpenConns(int) @@ -119,12 +112,12 @@ type EngineInterface interface { SetTZLocation(tz *time.Location) AddHook(hook contexts.Hook) ShowSQL(show ...bool) - Sync(...interface{}) error - Sync2(...interface{}) error - SyncWithOptions(SyncOptions, ...interface{}) (*SyncResult, error) + Sync(...any) error + Sync2(...any) error + SyncWithOptions(SyncOptions, ...any) (*SyncResult, error) StoreEngine(storeEngine string) *Session - TableInfo(bean interface{}) (*schemas.Table, error) - TableName(interface{}, ...bool) string + TableInfo(bean any) (*schemas.Table, error) + TableName(any, ...bool) string UnMapType(reflect.Type) EnableSessionID(bool) } diff --git a/convert/bool.go b/internal/convert/bool.go similarity index 95% rename from convert/bool.go rename to internal/convert/bool.go index 58b23f4b..83893f67 100644 --- a/convert/bool.go +++ b/internal/convert/bool.go @@ -11,7 +11,7 @@ import ( ) // AsBool convert interface as bool -func AsBool(src interface{}) (bool, error) { +func AsBool(src any) (bool, error) { switch v := src.(type) { case bool: return v, nil diff --git a/convert/conversion.go b/internal/convert/conversion.go similarity index 95% rename from convert/conversion.go rename to internal/convert/conversion.go index 5577e863..c260dbd4 100644 --- a/convert/conversion.go +++ b/internal/convert/conversion.go @@ -55,10 +55,10 @@ func cloneBytes(b []byte) []byte { // Assign copies to dest the value in src, converting it if possible. // An error is returned if the copy would result in loss of information. // dest should be a pointer type. -func Assign(dest, src interface{}, originalLocation *time.Location, convertedLocation *time.Location) error { +func Assign(dest, src any, originalLocation *time.Location, convertedLocation *time.Location) error { // Common cases, without reflect. switch s := src.(type) { - case *interface{}: + case *any: return Assign(dest, *s, originalLocation, convertedLocation) case string: switch d := dest.(type) { @@ -83,7 +83,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc } *d = string(s) return nil - case *interface{}: + case *any: if d == nil { return ErrNilPtr } @@ -110,7 +110,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc } case nil: switch d := dest.(type) { - case *interface{}: + case *any: if d == nil { return ErrNilPtr } @@ -295,7 +295,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc switch d := dest.(type) { case *string: - var sv = reflect.ValueOf(src) + sv := reflect.ValueOf(src) switch sv.Kind() { case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, @@ -315,7 +315,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc *d = bv.(bool) } return err - case *interface{}: + case *any: *d = src return nil } @@ -329,11 +329,11 @@ var ( ) // AssignValue assign src as dv -func AssignValue(dv reflect.Value, src interface{}) error { +func AssignValue(dv reflect.Value, src any) error { if src == nil { return nil } - if v, ok := src.(*interface{}); ok { + if v, ok := src.(*any); ok { return AssignValue(dv, *v) } diff --git a/convert/float.go b/internal/convert/float.go similarity index 96% rename from convert/float.go rename to internal/convert/float.go index 51b441ce..fa88552d 100644 --- a/convert/float.go +++ b/internal/convert/float.go @@ -13,7 +13,7 @@ import ( ) // AsFloat64 convets interface as float64 -func AsFloat64(src interface{}) (float64, error) { +func AsFloat64(src any) (float64, error) { switch v := src.(type) { case int: return float64(v), nil @@ -64,7 +64,7 @@ func AsFloat64(src interface{}) (float64, error) { } // AsBigFloat converts interface as big.Float -func AsBigFloat(src interface{}) (*big.Float, error) { +func AsBigFloat(src any) (*big.Float, error) { res := big.NewFloat(0) switch v := src.(type) { case int: diff --git a/convert/int.go b/internal/convert/int.go similarity index 95% rename from convert/int.go rename to internal/convert/int.go index 03994773..a41c2b9a 100644 --- a/convert/int.go +++ b/internal/convert/int.go @@ -13,7 +13,7 @@ import ( ) // AsInt64 converts interface as int64 -func AsInt64(src interface{}) (int64, error) { +func AsInt64(src any) (int64, error) { switch v := src.(type) { case int: return int64(v), nil @@ -112,7 +112,7 @@ func AsInt64(src interface{}) (int64, error) { } // AsUint64 converts interface as uint64 -func AsUint64(src interface{}) (uint64, error) { +func AsUint64(src any) (uint64, error) { switch v := src.(type) { case int: return uint64(v), nil @@ -171,7 +171,7 @@ type NullUint64 struct { } // Scan implements the Scanner interface. -func (n *NullUint64) Scan(value interface{}) error { +func (n *NullUint64) Scan(value any) error { if value == nil { n.Uint64, n.Valid = 0, false return nil @@ -201,7 +201,7 @@ type NullUint32 struct { } // Scan implements the Scanner interface. -func (n *NullUint32) Scan(value interface{}) error { +func (n *NullUint32) Scan(value any) error { if value == nil { n.Uint32, n.Valid = 0, false return nil diff --git a/convert/interface.go b/internal/convert/interface.go similarity index 92% rename from convert/interface.go rename to internal/convert/interface.go index 2cc8d9f4..58347b86 100644 --- a/convert/interface.go +++ b/internal/convert/interface.go @@ -11,7 +11,7 @@ import ( ) // Interface2Interface converts interface of pointer as interface of value -func Interface2Interface(userLocation *time.Location, v interface{}) (interface{}, error) { +func Interface2Interface(userLocation *time.Location, v any) (any, error) { if v == nil { return nil, nil } diff --git a/internal/convert/kind.go b/internal/convert/kind.go new file mode 100644 index 00000000..6123525a --- /dev/null +++ b/internal/convert/kind.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package convert + +import ( + "fmt" + "reflect" + "strconv" +) + +func AsKind(vv reflect.Value, tp reflect.Type) (any, error) { + switch tp.Kind() { + case reflect.Ptr: + return AsKind(vv.Elem(), tp.Elem()) + case reflect.Int64: + return vv.Int(), nil + case reflect.Int: + return int(vv.Int()), nil + case reflect.Int32: + return int32(vv.Int()), nil + case reflect.Int16: + return int16(vv.Int()), nil + case reflect.Int8: + return int8(vv.Int()), nil + case reflect.Uint64: + return vv.Uint(), nil + case reflect.Uint: + return uint(vv.Uint()), nil + case reflect.Uint32: + return uint32(vv.Uint()), nil + case reflect.Uint16: + return uint16(vv.Uint()), nil + case reflect.Uint8: + return uint8(vv.Uint()), nil + case reflect.String: + return vv.String(), nil + case reflect.Slice: + if tp.Elem().Kind() == reflect.Uint8 { + v, err := strconv.ParseInt(string(vv.Interface().([]byte)), 10, 64) + if err != nil { + return nil, err + } + return v, nil + } + } + return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv) +} diff --git a/convert/scanner.go b/internal/convert/scanner.go similarity index 78% rename from convert/scanner.go rename to internal/convert/scanner.go index 505d3be0..7ea47a81 100644 --- a/convert/scanner.go +++ b/internal/convert/scanner.go @@ -6,14 +6,12 @@ package convert import "database/sql" -var ( - _ sql.Scanner = &EmptyScanner{} -) +var _ sql.Scanner = &EmptyScanner{} // EmptyScanner represents an empty scanner which will ignore the scan type EmptyScanner struct{} // Scan implements sql.Scanner -func (EmptyScanner) Scan(value interface{}) error { +func (EmptyScanner) Scan(value any) error { return nil } diff --git a/convert/string.go b/internal/convert/string.go similarity index 95% rename from convert/string.go rename to internal/convert/string.go index de11fa01..d0050406 100644 --- a/convert/string.go +++ b/internal/convert/string.go @@ -12,7 +12,7 @@ import ( ) // AsString converts interface as string -func AsString(src interface{}) string { +func AsString(src any) string { switch v := src.(type) { case string: return v @@ -42,7 +42,7 @@ func AsString(src interface{}) string { } // AsBytes converts interface as bytes -func AsBytes(src interface{}) ([]byte, bool) { +func AsBytes(src any) ([]byte, bool) { switch t := src.(type) { case []byte: return t, true diff --git a/convert/time.go b/internal/convert/time.go similarity index 94% rename from convert/time.go rename to internal/convert/time.go index 8447214c..f12e8eee 100644 --- a/convert/time.go +++ b/internal/convert/time.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/internal/utils" ) // String2Time converts a string to time with original location @@ -85,10 +85,9 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t if err != nil { return nil, err } - dt = dt.AddDate(2006, 01, 02).In(convertedLocation) - // back to zero year - dt = dt.AddDate(-2006, -01, -02) - return &dt, nil + dt = dt.In(convertedLocation) + res := time.Date(0, time.January, 1, dt.Hour(), dt.Minute(), dt.Second(), 0, convertedLocation) + return &res, nil } else { i, err := strconv.ParseInt(s, 10, 64) if err == nil { @@ -103,7 +102,7 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t } // AsTime converts interface as time -func AsTime(src interface{}, dbLoc *time.Location, uiLoc *time.Location) (*time.Time, error) { +func AsTime(src any, dbLoc *time.Location, uiLoc *time.Location) (*time.Time, error) { switch t := src.(type) { case string: return String2Time(t, dbLoc, uiLoc) diff --git a/convert/time_test.go b/internal/convert/time_test.go similarity index 95% rename from convert/time_test.go rename to internal/convert/time_test.go index d7a9d5ad..e6b0f53b 100644 --- a/convert/time_test.go +++ b/internal/convert/time_test.go @@ -12,8 +12,7 @@ import ( ) func TestString2Time(t *testing.T) { - expectedLoc, err := time.LoadLocation("Asia/Shanghai") - assert.NoError(t, err) + expectedLoc := time.FixedZone("CST", 8*3600) cases := map[string]time.Time{ "2021-08-10": time.Date(2021, 8, 10, 8, 0, 0, 0, expectedLoc), diff --git a/core/db.go b/internal/core/db.go similarity index 82% rename from core/db.go rename to internal/core/db.go index b476ef9a..2296f14c 100644 --- a/core/db.go +++ b/internal/core/db.go @@ -13,24 +13,22 @@ import ( "regexp" "sync" - "xorm.io/xorm/contexts" - "xorm.io/xorm/log" - "xorm.io/xorm/names" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/names" ) -var ( - // DefaultCacheSize sets the default cache size - DefaultCacheSize = 200 -) +// DefaultCacheSize sets the default cache size +var DefaultCacheSize = 200 // MapToSlice map query and struct as sql and args -func MapToSlice(query string, mp interface{}) (string, []interface{}, error) { +func MapToSlice(query string, mp any) (string, []any, error) { vv := reflect.ValueOf(mp) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { - return "", []interface{}{}, ErrNoMapPointer + return "", []any{}, ErrNoMapPointer } - args := make([]interface{}, 0, len(vv.Elem().MapKeys())) + args := make([]any, 0, len(vv.Elem().MapKeys())) var err error query = re.ReplaceAllStringFunc(query, func(src string) string { v := vv.Elem().MapIndex(reflect.ValueOf(src[1:])) @@ -46,13 +44,13 @@ func MapToSlice(query string, mp interface{}) (string, []interface{}, error) { } // StructToSlice converts a query and struct as sql and args -func StructToSlice(query string, st interface{}) (string, []interface{}, error) { +func StructToSlice(query string, st any) (string, []any, error) { vv := reflect.ValueOf(st) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { - return "", []interface{}{}, ErrNoStructPointer + return "", []any{}, ErrNoStructPointer } - args := make([]interface{}, 0) + args := make([]any, 0) var err error query = re.ReplaceAllStringFunc(query, func(src string) string { fv := vv.Elem().FieldByName(src[1:]).Interface() @@ -69,7 +67,7 @@ func StructToSlice(query string, st interface{}) (string, []interface{}, error) return "?" }) if err != nil { - return "", []interface{}{}, err + return "", []any{}, err } return query, args, nil } @@ -79,9 +77,7 @@ type cacheStruct struct { idx int } -var ( - _ QueryExecuter = &DB{} -) +var _ QueryExecuter = &DB{} // DB is a wrap of sql.DB with extra contents type DB struct { @@ -142,7 +138,7 @@ func (db *DB) reflectNew(typ reflect.Type) reflect.Value { } // QueryContext overwrites sql.DB.QueryContext -func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { +func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) { hookCtx := contexts.NewContextHook(ctx, query, args) ctx, err := db.beforeProcess(hookCtx) if err != nil { @@ -160,12 +156,12 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{ } // Query overwrites sql.DB.Query -func (db *DB) Query(query string, args ...interface{}) (*Rows, error) { +func (db *DB) Query(query string, args ...any) (*Rows, error) { return db.QueryContext(context.Background(), query, args...) } // QueryMapContext executes query with parameters via map and context -func (db *DB) QueryMapContext(ctx context.Context, query string, mp interface{}) (*Rows, error) { +func (db *DB) QueryMapContext(ctx context.Context, query string, mp any) (*Rows, error) { query, args, err := MapToSlice(query, mp) if err != nil { return nil, err @@ -174,12 +170,12 @@ func (db *DB) QueryMapContext(ctx context.Context, query string, mp interface{}) } // QueryMap executes query with parameters via map -func (db *DB) QueryMap(query string, mp interface{}) (*Rows, error) { +func (db *DB) QueryMap(query string, mp any) (*Rows, error) { return db.QueryMapContext(context.Background(), query, mp) } // QueryStructContext query rows with struct -func (db *DB) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) { +func (db *DB) QueryStructContext(ctx context.Context, query string, st any) (*Rows, error) { query, args, err := StructToSlice(query, st) if err != nil { return nil, err @@ -188,12 +184,12 @@ func (db *DB) QueryStructContext(ctx context.Context, query string, st interface } // QueryStruct query rows with struct -func (db *DB) QueryStruct(query string, st interface{}) (*Rows, error) { +func (db *DB) QueryStruct(query string, st any) (*Rows, error) { return db.QueryStructContext(context.Background(), query, st) } // QueryRowContext query row with args -func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row { +func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row { rows, err := db.QueryContext(ctx, query, args...) if err != nil { return &Row{nil, err} @@ -202,12 +198,12 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa } // QueryRow query row with args -func (db *DB) QueryRow(query string, args ...interface{}) *Row { +func (db *DB) QueryRow(query string, args ...any) *Row { return db.QueryRowContext(context.Background(), query, args...) } // QueryRowMapContext query row with map -func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row { +func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp any) *Row { query, args, err := MapToSlice(query, mp) if err != nil { return &Row{nil, err} @@ -216,12 +212,12 @@ func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface } // QueryRowMap query row with map -func (db *DB) QueryRowMap(query string, mp interface{}) *Row { +func (db *DB) QueryRowMap(query string, mp any) *Row { return db.QueryRowMapContext(context.Background(), query, mp) } // QueryRowStructContext query row with struct -func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row { +func (db *DB) QueryRowStructContext(ctx context.Context, query string, st any) *Row { query, args, err := StructToSlice(query, st) if err != nil { return &Row{nil, err} @@ -230,18 +226,16 @@ func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interf } // QueryRowStruct query row with struct -func (db *DB) QueryRowStruct(query string, st interface{}) *Row { +func (db *DB) QueryRowStruct(query string, st any) *Row { return db.QueryRowStructContext(context.Background(), query, st) } -var ( - re = regexp.MustCompile(`[?](\w+)`) -) +var re = regexp.MustCompile(`[?](\w+)`) // ExecMapContext exec map with context.ContextHook // insert into (name) values (?) // insert into (name) values (?name) -func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{}) (sql.Result, error) { +func (db *DB) ExecMapContext(ctx context.Context, query string, mp any) (sql.Result, error) { query, args, err := MapToSlice(query, mp) if err != nil { return nil, err @@ -250,12 +244,12 @@ func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{}) } // ExecMap exec query with map -func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) { +func (db *DB) ExecMap(query string, mp any) (sql.Result, error) { return db.ExecMapContext(context.Background(), query, mp) } // ExecStructContext exec query with map -func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) { +func (db *DB) ExecStructContext(ctx context.Context, query string, st any) (sql.Result, error) { query, args, err := StructToSlice(query, st) if err != nil { return nil, err @@ -264,7 +258,7 @@ func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{ } // ExecContext exec query with args -func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { +func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) { hookCtx := contexts.NewContextHook(ctx, query, args) ctx, err := db.beforeProcess(hookCtx) if err != nil { @@ -279,7 +273,7 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{} } // ExecStruct exec query with struct -func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) { +func (db *DB) ExecStruct(query string, st any) (sql.Result, error) { return db.ExecStructContext(context.Background(), query, st) } diff --git a/core/db_test.go b/internal/core/db_test.go similarity index 98% rename from core/db_test.go rename to internal/core/db_test.go index a9c19392..6503bb49 100644 --- a/core/db_test.go +++ b/internal/core/db_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "xorm.io/xorm/names" + "xorm.io/xorm/v2/names" _ "github.com/go-sql-driver/mysql" _ "github.com/mattn/go-sqlite3" @@ -239,7 +239,7 @@ func BenchmarkSliceInterfaceQuery(b *testing.B) { } for rows.Next() { - slice := make([]interface{}, len(cols)) + slice := make([]any, len(cols)) err = rows.ScanSlice(&slice) if err != nil { b.Error(err) @@ -394,7 +394,7 @@ func BenchmarkMapInterfaceQuery(b *testing.B) { } for rows.Next() { - m := make(map[string]interface{}) + m := make(map[string]any) err = rows.ScanMap(&m) if err != nil { b.Error(err) @@ -551,7 +551,7 @@ func BenchmarkExecMap(b *testing.B) { b.StartTimer() - mp := map[string]interface{}{ + mp := map[string]any{ "name": "xlw", "title": "tester", "age": 1.2, @@ -582,7 +582,7 @@ func TestExecMap(t *testing.T) { t.Error(err) } - mp := map[string]interface{}{ + mp := map[string]any{ "name": "xlw", "title": "tester", "age": 1.2, @@ -625,7 +625,8 @@ func TestExecStruct(t *testing.T) { t.Error(err) } - user := User{Name: "xlw", + user := User{ + Name: "xlw", Title: "tester", Age: 1.2, Alias: "lunny", @@ -670,7 +671,8 @@ func BenchmarkExecStruct(b *testing.B) { b.StartTimer() - user := User{Name: "xlw", + user := User{ + Name: "xlw", Title: "tester", Age: 1.2, Alias: "lunny", diff --git a/core/error.go b/internal/core/error.go similarity index 100% rename from core/error.go rename to internal/core/error.go diff --git a/core/interface.go b/internal/core/interface.go similarity index 66% rename from core/interface.go rename to internal/core/interface.go index a5c8e4e2..d5ebb895 100644 --- a/core/interface.go +++ b/internal/core/interface.go @@ -7,12 +7,12 @@ import ( // Queryer represents an interface to query a SQL to get data from database type Queryer interface { - QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) + QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) } // Executer represents an interface to execute a SQL type Executer interface { - ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) + ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) } // QueryExecuter combines the Queryer and Executer diff --git a/core/rows.go b/internal/core/rows.go similarity index 88% rename from core/rows.go rename to internal/core/rows.go index 75d6ebf0..42ab762b 100644 --- a/core/rows.go +++ b/internal/core/rows.go @@ -24,9 +24,9 @@ func (rs *Rows) ToMapString() ([]map[string]string, error) { return nil, err } - var results = make([]map[string]string, 0, 10) + results := make([]map[string]string, 0, 10) for rs.Next() { - var record = make(map[string]string, len(cols)) + record := make(map[string]string, len(cols)) err = rs.ScanMap(&record) if err != nil { return nil, err @@ -37,7 +37,7 @@ func (rs *Rows) ToMapString() ([]map[string]string, error) { } // ScanStructByIndex scan data to a struct's pointer according field index -func (rs *Rows) ScanStructByIndex(dest ...interface{}) error { +func (rs *Rows) ScanStructByIndex(dest ...any) error { if len(dest) == 0 { return errors.New("at least one struct") } @@ -56,9 +56,9 @@ func (rs *Rows) ScanStructByIndex(dest ...interface{}) error { if err != nil { return err } - newDest := make([]interface{}, len(cols)) + newDest := make([]any, len(cols)) - var i = 0 + i := 0 for _, vvv := range vvvs { for j := 0; j < vvv.NumField(); j++ { newDest[i] = vvv.Field(j).Addr().Interface() @@ -97,7 +97,7 @@ func fieldByName(v reflect.Value, name string) reflect.Value { } // ScanStructByName scan data to a struct's pointer according field name -func (rs *Rows) ScanStructByName(dest interface{}) error { +func (rs *Rows) ScanStructByName(dest any) error { vv := reflect.ValueOf(dest) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { return errors.New("dest should be a struct's pointer") @@ -108,7 +108,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error { return err } - newDest := make([]interface{}, len(cols)) + newDest := make([]any, len(cols)) var v EmptyScanner for j, name := range cols { f := fieldByName(vv.Elem(), rs.db.Mapper.Table2Obj(name)) @@ -123,7 +123,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error { } // ScanSlice scan data to a slice's pointer, slice's length should equal to columns' number -func (rs *Rows) ScanSlice(dest interface{}) error { +func (rs *Rows) ScanSlice(dest any) error { vv := reflect.ValueOf(dest) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice { return errors.New("dest should be a slice's pointer") @@ -135,7 +135,7 @@ func (rs *Rows) ScanSlice(dest interface{}) error { return err } - newDest := make([]interface{}, len(cols)) + newDest := make([]any, len(cols)) for j := 0; j < len(cols); j++ { if j >= vvv.Len() { @@ -158,7 +158,7 @@ func (rs *Rows) ScanSlice(dest interface{}) error { } // ScanMap scan data to a map's pointer -func (rs *Rows) ScanMap(dest interface{}) error { +func (rs *Rows) ScanMap(dest any) error { vv := reflect.ValueOf(dest) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { return errors.New("dest should be a map's pointer") @@ -169,7 +169,7 @@ func (rs *Rows) ScanMap(dest interface{}) error { return err } - newDest := make([]interface{}, len(cols)) + newDest := make([]any, len(cols)) vvv := vv.Elem() for i := range cols { @@ -217,7 +217,7 @@ func (row *Row) Columns() ([]string, error) { } // Scan retrieves all row column values -func (row *Row) Scan(dest ...interface{}) error { +func (row *Row) Scan(dest ...any) error { if row.err != nil { return row.err } @@ -244,7 +244,7 @@ func (row *Row) Scan(dest ...interface{}) error { } // ScanStructByName retrieves all row column values into a struct -func (row *Row) ScanStructByName(dest interface{}) error { +func (row *Row) ScanStructByName(dest any) error { if row.err != nil { return row.err } @@ -265,7 +265,7 @@ func (row *Row) ScanStructByName(dest interface{}) error { } // ScanStructByIndex retrieves all row column values into a struct -func (row *Row) ScanStructByIndex(dest interface{}) error { +func (row *Row) ScanStructByIndex(dest any) error { if row.err != nil { return row.err } @@ -286,7 +286,7 @@ func (row *Row) ScanStructByIndex(dest interface{}) error { } // ScanSlice scan data to a slice's pointer, slice's length should equal to columns' number -func (row *Row) ScanSlice(dest interface{}) error { +func (row *Row) ScanSlice(dest any) error { if row.err != nil { return row.err } @@ -308,7 +308,7 @@ func (row *Row) ScanSlice(dest interface{}) error { } // ScanMap scan data to a map's pointer -func (row *Row) ScanMap(dest interface{}) error { +func (row *Row) ScanMap(dest any) error { if row.err != nil { return row.err } @@ -336,7 +336,7 @@ func (row *Row) ToMapString() (map[string]string, error) { return nil, err } - var record = make(map[string]string, len(cols)) + record := make(map[string]string, len(cols)) err = row.ScanMap(&record) if err != nil { return nil, err diff --git a/core/scan.go b/internal/core/scan.go similarity index 84% rename from core/scan.go rename to internal/core/scan.go index 1e7e4525..7ba3909f 100644 --- a/core/scan.go +++ b/internal/core/scan.go @@ -13,12 +13,10 @@ import ( // NullTime defines a customize type NullTime type NullTime time.Time -var ( - _ driver.Valuer = NullTime{} -) +var _ driver.Valuer = NullTime{} // Scan implements driver.Valuer -func (ns *NullTime) Scan(value interface{}) error { +func (ns *NullTime) Scan(value any) error { if value == nil { return nil } @@ -33,7 +31,7 @@ func (ns NullTime) Value() (driver.Value, error) { return (time.Time)(ns).Format("2006-01-02 15:04:05"), nil } -func convertTime(dest *NullTime, src interface{}) error { +func convertTime(dest *NullTime, src any) error { // Common cases, without reflect. switch s := src.(type) { case string: @@ -61,10 +59,9 @@ func convertTime(dest *NullTime, src interface{}) error { } // EmptyScanner represents an empty scanner -type EmptyScanner struct { -} +type EmptyScanner struct{} // Scan implements -func (EmptyScanner) Scan(src interface{}) error { +func (EmptyScanner) Scan(src any) error { return nil } diff --git a/core/stmt.go b/internal/core/stmt.go similarity index 75% rename from core/stmt.go rename to internal/core/stmt.go index 3247efed..0cce830c 100644 --- a/core/stmt.go +++ b/internal/core/stmt.go @@ -10,7 +10,7 @@ import ( "errors" "reflect" - "xorm.io/xorm/contexts" + "xorm.io/xorm/v2/contexts" ) // Stmt reprents a stmt objects @@ -49,13 +49,13 @@ func (db *DB) Prepare(query string) (*Stmt, error) { } // ExecMapContext execute with map -func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, error) { +func (s *Stmt) ExecMapContext(ctx context.Context, mp any) (sql.Result, error) { vv := reflect.ValueOf(mp) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { return nil, errors.New("mp should be a map's pointer") } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() } @@ -63,18 +63,18 @@ func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result, } // ExecMap executes with map -func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) { +func (s *Stmt) ExecMap(mp any) (sql.Result, error) { return s.ExecMapContext(context.Background(), mp) } // ExecStructContext executes with struct -func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Result, error) { +func (s *Stmt) ExecStructContext(ctx context.Context, st any) (sql.Result, error) { vv := reflect.ValueOf(st) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { return nil, errors.New("mp should be a map's pointer") } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().FieldByName(k).Interface() } @@ -82,12 +82,12 @@ func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Resul } // ExecStruct executes with struct -func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) { +func (s *Stmt) ExecStruct(st any) (sql.Result, error) { return s.ExecStructContext(context.Background(), st) } // ExecContext with args -func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) { +func (s *Stmt) ExecContext(ctx context.Context, args ...any) (sql.Result, error) { hookCtx := contexts.NewContextHook(ctx, s.query, args) ctx, err := s.db.beforeProcess(hookCtx) if err != nil { @@ -102,7 +102,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result } // QueryContext query with args -func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) { +func (s *Stmt) QueryContext(ctx context.Context, args ...any) (*Rows, error) { hookCtx := contexts.NewContextHook(ctx, s.query, args) ctx, err := s.db.beforeProcess(hookCtx) if err != nil { @@ -117,18 +117,18 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er } // Query query with args -func (s *Stmt) Query(args ...interface{}) (*Rows, error) { +func (s *Stmt) Query(args ...any) (*Rows, error) { return s.QueryContext(context.Background(), args...) } // QueryMapContext query with map -func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, error) { +func (s *Stmt) QueryMapContext(ctx context.Context, mp any) (*Rows, error) { vv := reflect.ValueOf(mp) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { return nil, errors.New("mp should be a map's pointer") } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() } @@ -137,18 +137,18 @@ func (s *Stmt) QueryMapContext(ctx context.Context, mp interface{}) (*Rows, erro } // QueryMap query with map -func (s *Stmt) QueryMap(mp interface{}) (*Rows, error) { +func (s *Stmt) QueryMap(mp any) (*Rows, error) { return s.QueryMapContext(context.Background(), mp) } // QueryStructContext query with struct -func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, error) { +func (s *Stmt) QueryStructContext(ctx context.Context, st any) (*Rows, error) { vv := reflect.ValueOf(st) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { return nil, errors.New("mp should be a map's pointer") } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().FieldByName(k).Interface() } @@ -157,29 +157,29 @@ func (s *Stmt) QueryStructContext(ctx context.Context, st interface{}) (*Rows, e } // QueryStruct query with struct -func (s *Stmt) QueryStruct(st interface{}) (*Rows, error) { +func (s *Stmt) QueryStruct(st any) (*Rows, error) { return s.QueryStructContext(context.Background(), st) } // QueryRowContext query row with args -func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row { +func (s *Stmt) QueryRowContext(ctx context.Context, args ...any) *Row { rows, err := s.QueryContext(ctx, args...) return &Row{rows, err} } // QueryRow query row with args -func (s *Stmt) QueryRow(args ...interface{}) *Row { +func (s *Stmt) QueryRow(args ...any) *Row { return s.QueryRowContext(context.Background(), args...) } // QueryRowMapContext query row with map -func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row { +func (s *Stmt) QueryRowMapContext(ctx context.Context, mp any) *Row { vv := reflect.ValueOf(mp) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { return &Row{nil, errors.New("mp should be a map's pointer")} } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() } @@ -188,18 +188,18 @@ func (s *Stmt) QueryRowMapContext(ctx context.Context, mp interface{}) *Row { } // QueryRowMap query row with map -func (s *Stmt) QueryRowMap(mp interface{}) *Row { +func (s *Stmt) QueryRowMap(mp any) *Row { return s.QueryRowMapContext(context.Background(), mp) } // QueryRowStructContext query row with struct -func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row { +func (s *Stmt) QueryRowStructContext(ctx context.Context, st any) *Row { vv := reflect.ValueOf(st) if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { return &Row{nil, errors.New("st should be a struct's pointer")} } - args := make([]interface{}, len(s.names)) + args := make([]any, len(s.names)) for k, i := range s.names { args[i] = vv.Elem().FieldByName(k).Interface() } @@ -208,6 +208,6 @@ func (s *Stmt) QueryRowStructContext(ctx context.Context, st interface{}) *Row { } // QueryRowStruct query row with struct -func (s *Stmt) QueryRowStruct(st interface{}) *Row { +func (s *Stmt) QueryRowStruct(st any) *Row { return s.QueryRowStructContext(context.Background(), st) } diff --git a/core/tx.go b/internal/core/tx.go similarity index 86% rename from core/tx.go rename to internal/core/tx.go index a2f745f8..2988133b 100644 --- a/core/tx.go +++ b/internal/core/tx.go @@ -8,12 +8,10 @@ import ( "context" "database/sql" - "xorm.io/xorm/contexts" + "xorm.io/xorm/v2/contexts" ) -var ( - _ QueryExecuter = &Tx{} -) +var _ QueryExecuter = &Tx{} // Tx represents a transaction type Tx struct { @@ -105,7 +103,7 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt { } // ExecMapContext executes query with args in a map -func (tx *Tx) ExecMapContext(ctx context.Context, query string, mp interface{}) (sql.Result, error) { +func (tx *Tx) ExecMapContext(ctx context.Context, query string, mp any) (sql.Result, error) { query, args, err := MapToSlice(query, mp) if err != nil { return nil, err @@ -114,12 +112,12 @@ func (tx *Tx) ExecMapContext(ctx context.Context, query string, mp interface{}) } // ExecMap executes query with args in a map -func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) { +func (tx *Tx) ExecMap(query string, mp any) (sql.Result, error) { return tx.ExecMapContext(context.Background(), query, mp) } // ExecStructContext executes query with args in a struct -func (tx *Tx) ExecStructContext(ctx context.Context, query string, st interface{}) (sql.Result, error) { +func (tx *Tx) ExecStructContext(ctx context.Context, query string, st any) (sql.Result, error) { query, args, err := StructToSlice(query, st) if err != nil { return nil, err @@ -128,7 +126,7 @@ func (tx *Tx) ExecStructContext(ctx context.Context, query string, st interface{ } // ExecContext executes a query with args -func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) { +func (tx *Tx) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error) { hookCtx := contexts.NewContextHook(ctx, query, args) ctx, err := tx.db.beforeProcess(hookCtx) if err != nil { @@ -143,12 +141,12 @@ func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{} } // ExecStruct executes query with args in a struct -func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) { +func (tx *Tx) ExecStruct(query string, st any) (sql.Result, error) { return tx.ExecStructContext(context.Background(), query, st) } // QueryContext query with args -func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { +func (tx *Tx) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) { hookCtx := contexts.NewContextHook(ctx, query, args) ctx, err := tx.db.beforeProcess(hookCtx) if err != nil { @@ -166,12 +164,12 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{ } // Query query with args -func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) { +func (tx *Tx) Query(query string, args ...any) (*Rows, error) { return tx.QueryContext(context.Background(), query, args...) } // QueryMapContext query with args in a map -func (tx *Tx) QueryMapContext(ctx context.Context, query string, mp interface{}) (*Rows, error) { +func (tx *Tx) QueryMapContext(ctx context.Context, query string, mp any) (*Rows, error) { query, args, err := MapToSlice(query, mp) if err != nil { return nil, err @@ -180,12 +178,12 @@ func (tx *Tx) QueryMapContext(ctx context.Context, query string, mp interface{}) } // QueryMap query with args in a map -func (tx *Tx) QueryMap(query string, mp interface{}) (*Rows, error) { +func (tx *Tx) QueryMap(query string, mp any) (*Rows, error) { return tx.QueryMapContext(context.Background(), query, mp) } // QueryStructContext query with args in struct -func (tx *Tx) QueryStructContext(ctx context.Context, query string, st interface{}) (*Rows, error) { +func (tx *Tx) QueryStructContext(ctx context.Context, query string, st any) (*Rows, error) { query, args, err := StructToSlice(query, st) if err != nil { return nil, err @@ -194,23 +192,23 @@ func (tx *Tx) QueryStructContext(ctx context.Context, query string, st interface } // QueryStruct query with args in struct -func (tx *Tx) QueryStruct(query string, st interface{}) (*Rows, error) { +func (tx *Tx) QueryStruct(query string, st any) (*Rows, error) { return tx.QueryStructContext(context.Background(), query, st) } // QueryRowContext query one row with args -func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row { +func (tx *Tx) QueryRowContext(ctx context.Context, query string, args ...any) *Row { rows, err := tx.QueryContext(ctx, query, args...) return &Row{rows, err} } // QueryRow query one row with args -func (tx *Tx) QueryRow(query string, args ...interface{}) *Row { +func (tx *Tx) QueryRow(query string, args ...any) *Row { return tx.QueryRowContext(context.Background(), query, args...) } // QueryRowMapContext query one row with args in a map -func (tx *Tx) QueryRowMapContext(ctx context.Context, query string, mp interface{}) *Row { +func (tx *Tx) QueryRowMapContext(ctx context.Context, query string, mp any) *Row { query, args, err := MapToSlice(query, mp) if err != nil { return &Row{nil, err} @@ -219,12 +217,12 @@ func (tx *Tx) QueryRowMapContext(ctx context.Context, query string, mp interface } // QueryRowMap query one row with args in a map -func (tx *Tx) QueryRowMap(query string, mp interface{}) *Row { +func (tx *Tx) QueryRowMap(query string, mp any) *Row { return tx.QueryRowMapContext(context.Background(), query, mp) } // QueryRowStructContext query one row with args in struct -func (tx *Tx) QueryRowStructContext(ctx context.Context, query string, st interface{}) *Row { +func (tx *Tx) QueryRowStructContext(ctx context.Context, query string, st any) *Row { query, args, err := StructToSlice(query, st) if err != nil { return &Row{nil, err} @@ -233,6 +231,6 @@ func (tx *Tx) QueryRowStructContext(ctx context.Context, query string, st interf } // QueryRowStruct query one row with args in struct -func (tx *Tx) QueryRowStruct(query string, st interface{}) *Row { +func (tx *Tx) QueryRowStruct(query string, st any) *Row { return tx.QueryRowStructContext(context.Background(), query, st) } diff --git a/internal/json/gojson.go b/internal/json/gojson.go index 9bfa5c29..06ea830c 100644 --- a/internal/json/gojson.go +++ b/internal/json/gojson.go @@ -19,11 +19,11 @@ func init() { type GOjson struct{} // Marshal implements JSONInterface -func (GOjson) Marshal(v interface{}) ([]byte, error) { +func (GOjson) Marshal(v any) ([]byte, error) { return gojson.Marshal(v) } // Unmarshal implements JSONInterface -func (GOjson) Unmarshal(data []byte, v interface{}) error { +func (GOjson) Unmarshal(data []byte, v any) error { return gojson.Unmarshal(data, v) } diff --git a/internal/json/json.go b/internal/json/json.go index ef52f51f..02b2adc7 100644 --- a/internal/json/json.go +++ b/internal/json/json.go @@ -8,24 +8,22 @@ import "encoding/json" // Interface represents an interface to handle json data type Interface interface { - Marshal(v interface{}) ([]byte, error) - Unmarshal(data []byte, v interface{}) error + Marshal(v any) ([]byte, error) + Unmarshal(data []byte, v any) error } -var ( - // DefaultJSONHandler default json handler - DefaultJSONHandler Interface = StdJSON{} -) +// DefaultJSONHandler default json handler +var DefaultJSONHandler Interface = StdJSON{} // StdJSON implements JSONInterface via encoding/json type StdJSON struct{} // Marshal implements JSONInterface -func (StdJSON) Marshal(v interface{}) ([]byte, error) { +func (StdJSON) Marshal(v any) ([]byte, error) { return json.Marshal(v) } // Unmarshal implements JSONInterface -func (StdJSON) Unmarshal(data []byte, v interface{}) error { +func (StdJSON) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) } diff --git a/internal/json/jsoniter.go b/internal/json/jsoniter.go index be93ac4e..6fc8a85d 100644 --- a/internal/json/jsoniter.go +++ b/internal/json/jsoniter.go @@ -19,11 +19,11 @@ func init() { type JSONiter struct{} // Marshal implements JSONInterface -func (JSONiter) Marshal(v interface{}) ([]byte, error) { +func (JSONiter) Marshal(v any) ([]byte, error) { return jsoniter.Marshal(v) } // Unmarshal implements JSONInterface -func (JSONiter) Unmarshal(data []byte, v interface{}) error { +func (JSONiter) Unmarshal(data []byte, v any) error { return jsoniter.Unmarshal(data, v) } diff --git a/internal/statements/statement_args.go b/internal/statements/args.go similarity index 93% rename from internal/statements/statement_args.go rename to internal/statements/args.go index 727d5977..25959b00 100644 --- a/internal/statements/statement_args.go +++ b/internal/statements/args.go @@ -6,11 +6,11 @@ package statements import ( "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) // WriteArg writes an arg -func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) error { +func (statement *Statement) WriteArg(w *builder.BytesWriter, arg any) error { switch argv := arg.(type) { case *builder.Builder: if _, err := w.WriteString("("); err != nil { @@ -40,7 +40,7 @@ func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) er } // WriteArgs writes args -func (statement *Statement) WriteArgs(w *builder.BytesWriter, args []interface{}) error { +func (statement *Statement) WriteArgs(w *builder.BytesWriter, args []any) error { for i, arg := range args { if err := statement.WriteArg(w, arg); err != nil { return err diff --git a/internal/statements/cache.go b/internal/statements/cache.go deleted file mode 100644 index 9dd76754..00000000 --- a/internal/statements/cache.go +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2019 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package statements - -import ( - "fmt" - "strconv" - "strings" - - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" -) - -// ConvertIDSQL converts SQL with id -func (statement *Statement) ConvertIDSQL(sqlStr string) string { - if statement.RefTable != nil { - cols := statement.RefTable.PKColumns() - if len(cols) == 0 { - return "" - } - - colstrs := statement.joinColumns(cols, false) - sqls := utils.SplitNNoCase(sqlStr, " from ", 2) - if len(sqls) != 2 { - return "" - } - - var b strings.Builder - b.WriteString("SELECT ") - pLimitN := statement.LimitN - if pLimitN != nil && statement.dialect.URI().DBType == schemas.MSSQL { - b.WriteString("TOP ") - b.WriteString(strconv.Itoa(*pLimitN)) - b.WriteString(" ") - } - b.WriteString(colstrs) - b.WriteString(" FROM ") - b.WriteString(sqls[1]) - - return b.String() - } - return "" -} - -// ConvertUpdateSQL converts update SQL -func (statement *Statement) ConvertUpdateSQL(sqlStr string) (string, string) { - if statement.RefTable == nil || len(statement.RefTable.PrimaryKeys) != 1 { - return "", "" - } - - colstrs := statement.joinColumns(statement.RefTable.PKColumns(), true) - sqls := utils.SplitNNoCase(sqlStr, "where", 2) - if len(sqls) != 2 { - if len(sqls) == 1 { - return sqls[0], fmt.Sprintf("SELECT %v FROM %v", - colstrs, statement.quote(statement.TableName())) - } - return "", "" - } - - whereStr := sqls[1] - - // TODO: for postgres only, if any other database? - var paraStr string - if statement.dialect.URI().DBType == schemas.POSTGRES { - paraStr = "$" - } else if statement.dialect.URI().DBType == schemas.MSSQL { - paraStr = ":" - } - - if paraStr != "" { - if strings.Contains(sqls[1], paraStr) { - dollers := strings.Split(sqls[1], paraStr) - whereStr = dollers[0] - for i, c := range dollers[1:] { - ccs := strings.SplitN(c, " ", 2) - whereStr += fmt.Sprintf(paraStr+"%v %v", i+1, ccs[1]) - } - } - } - - return sqls[0], fmt.Sprintf("SELECT %v FROM %v WHERE %v", - colstrs, statement.quote(statement.TableName()), - whereStr) -} diff --git a/internal/statements/column_map.go b/internal/statements/column_map.go index bb764b4e..bd93916e 100644 --- a/internal/statements/column_map.go +++ b/internal/statements/column_map.go @@ -7,7 +7,7 @@ package statements import ( "strings" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) type columnMap []string diff --git a/internal/statements/cond.go b/internal/statements/cond.go index dfc6c208..97410ba3 100644 --- a/internal/statements/cond.go +++ b/internal/statements/cond.go @@ -6,7 +6,7 @@ package statements import ( "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) type QuoteReplacer struct { @@ -27,17 +27,17 @@ func (statement *Statement) QuoteReplacer(w *builder.BytesWriter) *QuoteReplacer } // Where add Where statement -func (statement *Statement) Where(query interface{}, args ...interface{}) *Statement { +func (statement *Statement) Where(query any, args ...any) *Statement { return statement.And(query, args...) } // And add Where & and statement -func (statement *Statement) And(query interface{}, args ...interface{}) *Statement { +func (statement *Statement) And(query any, args ...any) *Statement { switch qr := query.(type) { case string: cond := builder.Expr(qr, args...) statement.cond = statement.cond.And(cond) - case map[string]interface{}: + case map[string]any: cond := make(builder.Eq) for k, v := range qr { cond[statement.quote(k)] = v @@ -58,12 +58,12 @@ func (statement *Statement) And(query interface{}, args ...interface{}) *Stateme } // Or add Where & Or statement -func (statement *Statement) Or(query interface{}, args ...interface{}) *Statement { +func (statement *Statement) Or(query any, args ...any) *Statement { switch qr := query.(type) { case string: cond := builder.Expr(qr, args...) statement.cond = statement.cond.Or(cond) - case map[string]interface{}: + case map[string]any: cond := make(builder.Eq) for k, v := range qr { cond[statement.quote(k)] = v @@ -83,14 +83,14 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen } // In generate "Where column IN (?) " statement -func (statement *Statement) In(column string, args ...interface{}) *Statement { +func (statement *Statement) In(column string, args ...any) *Statement { in := builder.In(statement.quote(column), args...) statement.cond = statement.cond.And(in) return statement } // NotIn generate "Where column NOT IN (?) " statement -func (statement *Statement) NotIn(column string, args ...interface{}) *Statement { +func (statement *Statement) NotIn(column string, args ...any) *Statement { notIn := builder.NotIn(statement.quote(column), args...) statement.cond = statement.cond.And(notIn) return statement diff --git a/internal/statements/delete.go b/internal/statements/delete.go index 6e859399..148efd6d 100644 --- a/internal/statements/delete.go +++ b/internal/statements/delete.go @@ -10,8 +10,8 @@ import ( "time" "xorm.io/builder" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) func (statement *Statement) writeDeleteOrder(w *builder.BytesWriter) error { @@ -84,10 +84,11 @@ func (statement *Statement) writeOrderCond(orderCondWriter *builder.BytesWriter, } } -func (statement *Statement) WriteDelete(realSQLWriter, deleteSQLWriter *builder.BytesWriter, nowTime func(*schemas.Column) (interface{}, time.Time, error)) error { +func (statement *Statement) WriteDelete(realSQLWriter *builder.BytesWriter, nowTime func(*schemas.Column) (any, time.Time, error)) error { tableNameNoQuote := statement.TableName() tableName := statement.dialect.Quoter().Quote(tableNameNoQuote) table := statement.RefTable + deleteSQLWriter := builder.NewWriter() if _, err := fmt.Fprint(deleteSQLWriter, "DELETE FROM ", tableName); err != nil { return err } diff --git a/internal/statements/expr.go b/internal/statements/expr.go index c2a2e1cc..3c2f4171 100644 --- a/internal/statements/expr.go +++ b/internal/statements/expr.go @@ -9,7 +9,7 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) // ErrUnsupportedExprType represents an error with unsupported express type @@ -24,7 +24,7 @@ func (err ErrUnsupportedExprType) Error() string { // Expr represents an SQL express type Expr struct { ColName string - Arg interface{} + Arg any } // WriteArgs writes args to the writer @@ -59,14 +59,14 @@ func (expr *Expr) WriteArgs(w *builder.BytesWriter) error { type exprParams []Expr func (exprs exprParams) ColNames() []string { - var cols = make([]string, 0, len(exprs)) + cols := make([]string, 0, len(exprs)) for _, expr := range exprs { cols = append(cols, expr.ColName) } return cols } -func (exprs *exprParams) Add(name string, arg interface{}) { +func (exprs *exprParams) Add(name string, arg any) { *exprs = append(*exprs, Expr{name, arg}) } diff --git a/internal/statements/insert.go b/internal/statements/insert.go index aa396431..1b9ed5e6 100644 --- a/internal/statements/insert.go +++ b/internal/statements/insert.go @@ -10,8 +10,8 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schemas.Table) error { @@ -27,7 +27,7 @@ func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schem } // GenInsertSQL generates insert beans SQL -func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) (string, []interface{}, error) { +func (statement *Statement) GenInsertSQL(colNames []string, args []any) (string, []any, error) { var ( buf = builder.NewWriter() exprs = statement.ExprColumns @@ -177,7 +177,7 @@ func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) } // GenInsertMapSQL generates insert map SQL -func (statement *Statement) GenInsertMapSQL(columns []string, args []interface{}) (string, []interface{}, error) { +func (statement *Statement) GenInsertMapSQL(columns []string, args []any) (string, []any, error) { var ( buf = builder.NewWriter() exprs = statement.ExprColumns @@ -242,7 +242,7 @@ func (statement *Statement) GenInsertMapSQL(columns []string, args []interface{} return buf.String(), buf.Args(), nil } -func (statement *Statement) GenInsertMultipleMapSQL(columns []string, argss [][]interface{}) (string, []interface{}, error) { +func (statement *Statement) GenInsertMultipleMapSQL(columns []string, argss [][]any) (string, []any, error) { var ( buf = builder.NewWriter() exprs = statement.ExprColumns diff --git a/internal/statements/join.go b/internal/statements/join.go index 740b31de..48e7403b 100644 --- a/internal/statements/join.go +++ b/internal/statements/join.go @@ -9,13 +9,13 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) // Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN -func (statement *Statement) Join(joinOP string, joinTable interface{}, condition interface{}, args ...interface{}) *Statement { +func (statement *Statement) Join(joinOP string, joinTable any, condition any, args ...any) *Statement { statement.joins = append(statement.joins, join{ op: joinOP, table: joinTable, diff --git a/internal/statements/order_by.go b/internal/statements/order_by.go index 04197fb7..a527630d 100644 --- a/internal/statements/order_by.go +++ b/internal/statements/order_by.go @@ -12,8 +12,8 @@ import ( ) type orderBy struct { - orderStr interface{} - orderArgs []interface{} + orderStr any + orderArgs []any direction string // ASC, DESC or "", "" means raw orderStr } @@ -97,7 +97,7 @@ func (statement *Statement) writeOrderBys(w *builder.BytesWriter) error { } // OrderBy generate "Order By order" statement -func (statement *Statement) OrderBy(order interface{}, args ...interface{}) *Statement { +func (statement *Statement) OrderBy(order any, args ...any) *Statement { ob := orderBy{order, args, ""} if err := ob.CheckValid(); err != nil { statement.LastError = err diff --git a/internal/statements/pagination.go b/internal/statements/pagination.go index 3c7a3913..33c001c6 100644 --- a/internal/statements/pagination.go +++ b/internal/statements/pagination.go @@ -9,12 +9,13 @@ import ( "fmt" "xorm.io/builder" - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) func (statement *Statement) writePagination(bw *builder.BytesWriter) error { dbType := statement.dialect.URI().DBType - if dbType == "mssql" || dbType == "oracle" { + if dbType == schemas.MSSQL || dbType == schemas.ORACLE { return statement.writeOffsetFetch(bw) } return statement.writeLimitOffset(bw) @@ -50,15 +51,15 @@ func (statement *Statement) writeOffsetFetch(w builder.Writer) error { } func (statement *Statement) writeWhereWithMssqlPagination(w *builder.BytesWriter) error { - if !statement.cond.IsValid() { - return statement.writeMssqlPaginationCond(w) - } - if _, err := fmt.Fprint(w, " WHERE "); err != nil { - return err - } - if err := statement.cond.WriteTo(statement.QuoteReplacer(w)); err != nil { - return err + if statement.cond.IsValid() { + if _, err := fmt.Fprint(w, " WHERE "); err != nil { + return err + } + if err := statement.cond.WriteTo(statement.QuoteReplacer(w)); err != nil { + return err + } } + return statement.writeMssqlPaginationCond(w) } @@ -115,15 +116,8 @@ func (statement *Statement) writeMssqlPaginationCond(w *builder.BytesWriter) err if _, err := fmt.Fprint(subWriter, "))"); err != nil { return err } - - if statement.cond.IsValid() { - if _, err := fmt.Fprint(w, " AND "); err != nil { - return err - } - } else { - if _, err := fmt.Fprint(w, " WHERE "); err != nil { - return err - } + if err := statement.writeWhereOrAnd(w, statement.cond.IsValid()); err != nil { + return err } return utils.WriteBuilder(w, subWriter) diff --git a/internal/statements/pk.go b/internal/statements/pk.go index 59da89c0..92340acf 100644 --- a/internal/statements/pk.go +++ b/internal/statements/pk.go @@ -9,7 +9,7 @@ import ( "reflect" "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) var ( @@ -36,7 +36,7 @@ func IsIDConditionWithNoTableErr(err error) bool { } // ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?" -func (statement *Statement) ID(id interface{}) *Statement { +func (statement *Statement) ID(id any) *Statement { switch t := id.(type) { case *schemas.PK: statement.idParam = *t @@ -91,7 +91,7 @@ func (statement *Statement) ProcessIDParam() error { } for i, col := range statement.RefTable.PKColumns() { - var colName = statement.colName(col, statement.TableName()) + colName := statement.colName(col, statement.TableName()) statement.cond = statement.cond.And(builder.Eq{colName: statement.idParam[i]}) } return nil diff --git a/internal/statements/query.go b/internal/statements/query.go index 8a9e59e4..092c5cf3 100644 --- a/internal/statements/query.go +++ b/internal/statements/query.go @@ -11,11 +11,11 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) // GenQuerySQL generate query SQL -func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []interface{}, error) { +func (statement *Statement) GenQuerySQL(sqlOrArgs ...any) (string, []any, error) { if len(sqlOrArgs) > 0 { return statement.ConvertSQLOrArgs(sqlOrArgs...) } @@ -40,7 +40,7 @@ func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []int } // GenSumSQL generates sum SQL -func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) { +func (statement *Statement) GenSumSQL(bean any, columns ...string) (string, []any, error) { if statement.RawSQL != "" { return statement.GenRawSQL(), statement.RawParams, nil } @@ -71,7 +71,7 @@ func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (stri } // GenGetSQL generates Get SQL -func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{}, error) { +func (statement *Statement) GenGetSQL(bean any) (string, []any, error) { var isStruct bool if bean != nil { v := rValue(bean) @@ -127,7 +127,7 @@ func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{}, } // GenCountSQL generates the SQL for counting -func (statement *Statement) GenCountSQL(beans ...interface{}) (string, []interface{}, error) { +func (statement *Statement) GenCountSQL(beans ...any) (string, []any, error) { if statement.RawSQL != "" { return statement.GenRawSQL(), statement.RawParams, nil } @@ -286,12 +286,12 @@ func (statement *Statement) writeSelect(buf *builder.BytesWriter, columnStr stri } // GenExistSQL generates Exist SQL -func (statement *Statement) GenExistSQL(bean ...interface{}) (string, []interface{}, error) { +func (statement *Statement) GenExistSQL(bean ...any) (string, []any, error) { if statement.RawSQL != "" { return statement.GenRawSQL(), statement.RawParams, nil } - var b interface{} + var b any if len(bean) > 0 { b = bean[0] beanValue := reflect.ValueOf(bean[0]) @@ -393,7 +393,7 @@ func (statement *Statement) genSelectColumnStr() string { } // GenFindSQL generates Find SQL -func (statement *Statement) GenFindSQL(autoCond builder.Cond) (string, []interface{}, error) { +func (statement *Statement) GenFindSQL(autoCond builder.Cond) (string, []any, error) { if statement.RawSQL != "" { return statement.GenRawSQL(), statement.RawParams, nil } diff --git a/internal/statements/select.go b/internal/statements/select.go index 59161d76..292e2da1 100644 --- a/internal/statements/select.go +++ b/internal/statements/select.go @@ -8,7 +8,7 @@ import ( "fmt" "strings" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) // Select replace select diff --git a/internal/statements/statement.go b/internal/statements/statement.go index 1d92b842..f29dd018 100644 --- a/internal/statements/statement.go +++ b/internal/statements/statement.go @@ -14,13 +14,13 @@ import ( "time" "xorm.io/builder" - "xorm.io/xorm/contexts" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/json" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" - "xorm.io/xorm/tags" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/json" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" + "xorm.io/xorm/v2/tags" ) var ( @@ -36,9 +36,9 @@ var ( type join struct { op string - table interface{} - condition interface{} - args []interface{} + table any + condition any + args []any } // Statement save all the sql info for executing SQL @@ -59,12 +59,11 @@ type Statement struct { AltTableName string tableName string RawSQL string - RawParams []interface{} + RawParams []any UseCascade bool UseAutoJoin bool StoreEngine string Charset string - UseCache bool UseAutoTime bool NoAutoCondition bool IsDistinct bool @@ -137,8 +136,7 @@ func (statement *Statement) Reset() { statement.tableName = "" statement.idParam = nil statement.RawSQL = "" - statement.RawParams = make([]interface{}, 0) - statement.UseCache = true + statement.RawParams = make([]any, 0) statement.UseAutoTime = true statement.NoAutoCondition = false statement.IsDistinct = false @@ -161,7 +159,7 @@ func (statement *Statement) Reset() { } // SQL adds raw sql statement -func (statement *Statement) SQL(query interface{}, args ...interface{}) *Statement { +func (statement *Statement) SQL(query any, args ...any) *Statement { switch t := query.(type) { case *builder.Builder: var err error @@ -194,12 +192,12 @@ func (statement *Statement) SetRefValue(v reflect.Value) error { return nil } -func rValue(bean interface{}) reflect.Value { +func rValue(bean any) reflect.Value { return reflect.Indirect(reflect.ValueOf(bean)) } // SetRefBean set ref bean -func (statement *Statement) SetRefBean(bean interface{}) error { +func (statement *Statement) SetRefBean(bean any) error { var err error statement.RefTable, err = statement.tagParser.ParseWithCache(rValue(bean)) if err != nil { @@ -214,7 +212,7 @@ func (statement *Statement) NeedTableName() bool { } // Incr Generate "Update ... Set column = column + arg" statement -func (statement *Statement) Incr(column string, arg ...interface{}) *Statement { +func (statement *Statement) Incr(column string, arg ...any) *Statement { if len(arg) > 0 { statement.IncrColumns.Add(column, arg[0]) } else { @@ -224,7 +222,7 @@ func (statement *Statement) Incr(column string, arg ...interface{}) *Statement { } // Decr Generate "Update ... Set column = column - arg" statement -func (statement *Statement) Decr(column string, arg ...interface{}) *Statement { +func (statement *Statement) Decr(column string, arg ...any) *Statement { if len(arg) > 0 { statement.DecrColumns.Add(column, arg[0]) } else { @@ -234,7 +232,7 @@ func (statement *Statement) Decr(column string, arg ...interface{}) *Statement { } // SetExpr Generate "Update ... Set column = {expression}" statement -func (statement *Statement) SetExpr(column string, expression interface{}) *Statement { +func (statement *Statement) SetExpr(column string, expression any) *Statement { if e, ok := expression.(string); ok { statement.ExprColumns.Add(column, statement.dialect.Quoter().Replace(e)) } else { @@ -273,7 +271,7 @@ func (statement *Statement) Limit(limit int, start ...int) *Statement { } // SetTable tempororily set table name, the parameter could be a string or a pointer of struct -func (statement *Statement) SetTable(tableNameOrBean interface{}) error { +func (statement *Statement) SetTable(tableNameOrBean any) error { v := rValue(tableNameOrBean) t := v.Type() if t.Kind() == reflect.Struct { @@ -367,7 +365,7 @@ func (statement *Statement) GenDelIndexSQL() []string { return sqls } -func (statement *Statement) asDBCond(fieldValue reflect.Value, fieldType reflect.Type, col *schemas.Column, allUseBool, requiredField bool) (interface{}, bool, error) { +func (statement *Statement) asDBCond(fieldValue reflect.Value, fieldType reflect.Type, col *schemas.Column, allUseBool, requiredField bool) (any, bool, error) { switch fieldType.Kind() { case reflect.Ptr: if fieldValue.IsNil() { @@ -503,7 +501,7 @@ func (statement *Statement) asDBCond(fieldValue reflect.Value, fieldType reflect return fieldValue.Interface(), true, nil } -func (statement *Statement) buildConds2(table *schemas.Table, bean interface{}, +func (statement *Statement) buildConds2(table *schemas.Table, bean any, includeVersion bool, includeUpdated bool, includeNil bool, includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool, mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool, @@ -601,13 +599,13 @@ func (statement *Statement) buildConds2(table *schemas.Table, bean interface{}, } // BuildConds builds condition -func (statement *Statement) BuildConds(table *schemas.Table, bean interface{}, includeVersion bool, includeUpdated bool, includeNil bool, includeAutoIncr bool, addedTableName bool) (builder.Cond, error) { +func (statement *Statement) BuildConds(table *schemas.Table, bean any, includeVersion bool, includeUpdated bool, includeNil bool, includeAutoIncr bool, addedTableName bool) (builder.Cond, error) { return statement.buildConds2(table, bean, includeVersion, includeUpdated, includeNil, includeAutoIncr, statement.allUseBool, statement.useAllCols, statement.unscoped, statement.MustColumnMap, statement.TableName(), statement.TableAlias, addedTableName) } // MergeConds merge conditions from bean and id -func (statement *Statement) MergeConds(bean interface{}) error { +func (statement *Statement) MergeConds(bean any) error { if !statement.NoAutoCondition && statement.RefTable != nil { addedTableName := len(statement.joins) > 0 autoCond, err := statement.BuildConds(statement.RefTable, bean, true, true, false, true, addedTableName) @@ -626,7 +624,7 @@ func (statement *Statement) quoteColumnStr(columnStr string) string { } // ConvertSQLOrArgs converts sql or args -func (statement *Statement) ConvertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) { +func (statement *Statement) ConvertSQLOrArgs(sqlOrArgs ...any) (string, []any, error) { sql, args, err := statement.convertSQLOrArgs(sqlOrArgs...) if err != nil { return "", nil, err @@ -634,11 +632,11 @@ func (statement *Statement) ConvertSQLOrArgs(sqlOrArgs ...interface{}) (string, return statement.ReplaceQuote(sql), args, nil } -func (statement *Statement) convertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) { +func (statement *Statement) convertSQLOrArgs(sqlOrArgs ...any) (string, []any, error) { switch sqlOrArgs[0].(type) { case string: if len(sqlOrArgs) > 1 { - newArgs := make([]interface{}, 0, len(sqlOrArgs)-1) + newArgs := make([]any, 0, len(sqlOrArgs)-1) for _, arg := range sqlOrArgs[1:] { if v, ok := arg.(time.Time); ok { newArgs = append(newArgs, v.In(statement.defaultTimeZone).Format("2006-01-02 15:04:05")) diff --git a/internal/statements/statement_test.go b/internal/statements/statement_test.go index 31428efa..7d549c96 100644 --- a/internal/statements/statement_test.go +++ b/internal/statements/statement_test.go @@ -12,11 +12,11 @@ import ( "time" "github.com/stretchr/testify/assert" - "xorm.io/xorm/caches" - "xorm.io/xorm/dialects" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" - "xorm.io/xorm/tags" + + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" + "xorm.io/xorm/v2/tags" _ "github.com/mattn/go-sqlite3" ) @@ -33,7 +33,7 @@ func TestMain(m *testing.M) { panic("unknow dialect") } - tagParser = tags.NewParser("xorm", dialect, names.SnakeMapper{}, names.SnakeMapper{}, caches.NewManager()) + tagParser = tags.NewParser("xorm", dialect, names.SnakeMapper{}, names.SnakeMapper{}) if tagParser == nil { panic("tags parser is nil") } @@ -88,7 +88,7 @@ func TestConvertSQLOrArgs(t *testing.T) { // ID int // del *time.Time `xorm:"deleted"` // } - args := []interface{}{ + args := []any{ "INSERT `table` (`id`, `del`) VALUES (?, ?)", 1, (*time.Time)(nil), } // before fix, here will panic diff --git a/internal/statements/table_name.go b/internal/statements/table_name.go index 1396b7df..94cdea3f 100644 --- a/internal/statements/table_name.go +++ b/internal/statements/table_name.go @@ -9,7 +9,7 @@ import ( "strings" "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) // TableName return current tableName diff --git a/internal/statements/update.go b/internal/statements/update.go index 5d71f34d..cd09e7a9 100644 --- a/internal/statements/update.go +++ b/internal/statements/update.go @@ -12,11 +12,11 @@ import ( "time" "xorm.io/builder" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/json" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/json" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) func (statement *Statement) ifAddColUpdate(col *schemas.Column, includeVersion, includeUpdated, includeNil, @@ -67,7 +67,7 @@ func (statement *Statement) ifAddColUpdate(col *schemas.Column, includeVersion, func (statement *Statement) BuildUpdates(tableValue reflect.Value, includeVersion, includeUpdated, includeNil, includeAutoIncr, update bool, -) ([]string, []interface{}, error) { +) ([]string, []any, error) { table := statement.RefTable allUseBool := statement.allUseBool useAllCols := statement.useAllCols @@ -75,7 +75,7 @@ func (statement *Statement) BuildUpdates(tableValue reflect.Value, nullableMap := statement.NullableMap colNames := make([]string, 0) - args := make([]interface{}, 0) + args := make([]any, 0) for _, col := range table.Columns() { ok, err := statement.ifAddColUpdate(col, includeVersion, includeUpdated, includeNil, @@ -122,7 +122,7 @@ func (statement *Statement) BuildUpdates(tableValue reflect.Value, } } - var val interface{} + var val any if fieldValue.CanAddr() { if structConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { @@ -350,6 +350,15 @@ func (statement *Statement) writeUpdateFrom(updateWriter *builder.BytesWriter) e return err } +func (statement *Statement) writeWhereOrAnd(updateWriter *builder.BytesWriter, hasConditions bool) error { + if hasConditions { + _, err := fmt.Fprint(updateWriter, " AND ") + return err + } + _, err := fmt.Fprint(updateWriter, " WHERE ") + return err +} + func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter, cond builder.Cond) error { if statement.LimitN == nil { return nil @@ -364,14 +373,8 @@ func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter, _, err := fmt.Fprintf(updateWriter, " LIMIT %d", limitValue) return err case schemas.SQLITE: - if cond.IsValid() { - if _, err := fmt.Fprint(updateWriter, " AND "); err != nil { - return err - } - } else { - if _, err := fmt.Fprint(updateWriter, " WHERE "); err != nil { - return err - } + if err := statement.writeWhereOrAnd(updateWriter, cond.IsValid()); err != nil { + return err } if _, err := fmt.Fprint(updateWriter, "rowid IN (SELECT rowid FROM ", statement.quote(tableName)); err != nil { return err @@ -385,14 +388,8 @@ func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter, _, err := fmt.Fprintf(updateWriter, " LIMIT %d)", limitValue) return err case schemas.POSTGRES: - if cond.IsValid() { - if _, err := fmt.Fprint(updateWriter, " AND "); err != nil { - return err - } - } else { - if _, err := fmt.Fprint(updateWriter, " WHERE "); err != nil { - return err - } + if err := statement.writeWhereOrAnd(updateWriter, cond.IsValid()); err != nil { + return err } if _, err := fmt.Fprint(updateWriter, "CTID IN (SELECT CTID FROM ", statement.quote(tableName)); err != nil { return err @@ -427,9 +424,9 @@ func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter, } } -func (statement *Statement) GenConditionsFromMap(m interface{}) ([]builder.Cond, error) { +func (statement *Statement) GenConditionsFromMap(m any) ([]builder.Cond, error) { switch t := m.(type) { - case map[string]interface{}: + case map[string]any: conds := []builder.Cond{} for k, v := range t { conds = append(conds, builder.Eq{k: v}) @@ -477,9 +474,9 @@ func (statement *Statement) writeVersionIncrSet(w builder.Writer, v reflect.Valu return nil } -func (statement *Statement) writeIncrSets(w builder.Writer, hasPreviousSet bool) error { +func (statement *Statement) writeIncrSets(w builder.Writer, hasPreviousSets bool) error { for i, expr := range statement.IncrColumns { - if i > 0 || hasPreviousSet { + if i > 0 || hasPreviousSets { if _, err := fmt.Fprint(w, ", "); err != nil { return err } @@ -492,10 +489,10 @@ func (statement *Statement) writeIncrSets(w builder.Writer, hasPreviousSet bool) return nil } -func (statement *Statement) writeDecrSets(w builder.Writer, hasPreviousSet bool) error { +func (statement *Statement) writeDecrSets(w builder.Writer, hasPreviousSets bool) error { // for update action to like "column = column - ?" for i, expr := range statement.DecrColumns { - if i > 0 || hasPreviousSet { + if i > 0 || hasPreviousSets { if _, err := fmt.Fprint(w, ", "); err != nil { return err } @@ -508,10 +505,10 @@ func (statement *Statement) writeDecrSets(w builder.Writer, hasPreviousSet bool) return nil } -func (statement *Statement) writeExprSets(w *builder.BytesWriter, hasPreviousSet bool) error { +func (statement *Statement) writeExprSets(w *builder.BytesWriter, hasPreviousSets bool) error { // for update action to like "column = expression" for i, expr := range statement.ExprColumns { - if i > 0 || hasPreviousSet { + if i > 0 || hasPreviousSets { if _, err := fmt.Fprint(w, ", "); err != nil { return err } @@ -544,41 +541,70 @@ func (statement *Statement) writeExprSets(w *builder.BytesWriter, hasPreviousSet return nil } -func (statement *Statement) writeUpdateSets(w *builder.BytesWriter, v reflect.Value, colNames []string, args []interface{}) error { - previousLen := w.Len() - for i, colName := range colNames { - if i > 0 { - if _, err := fmt.Fprint(w, ", "); err != nil { +func (statement *Statement) writeSetColumns(colNames []string, args []any) func(w *builder.BytesWriter) error { + return func(w *builder.BytesWriter) error { + if len(colNames) == 0 { + return nil + } + if len(colNames) != len(args) { + return fmt.Errorf("columns elements %d but args elements %d", len(colNames), len(args)) + } + for i, colName := range colNames { + if i > 0 { + if _, err := fmt.Fprint(w, ", "); err != nil { + return err + } + } + if _, err := fmt.Fprint(w, colName); err != nil { return err } } - if _, err := fmt.Fprint(w, colName); err != nil { - return err - } + w.Append(args...) + return nil } - w.Append(args...) +} - if err := statement.writeIncrSets(w, w.Len() > previousLen); err != nil { +func (statement *Statement) writeUpdateSets(w *builder.BytesWriter, v reflect.Value, colNames []string, args []any) error { + // write set + if _, err := fmt.Fprint(w, " SET "); err != nil { + return err + } + previousLen := w.Len() + + if err := statement.writeSetColumns(colNames, args)(w); err != nil { return err } - if err := statement.writeDecrSets(w, w.Len() > previousLen); err != nil { + setNumber := len(colNames) + if err := statement.writeIncrSets(w, setNumber > 0); err != nil { return err } - if err := statement.writeExprSets(w, w.Len() > previousLen); err != nil { + setNumber += len(statement.IncrColumns) + if err := statement.writeDecrSets(w, setNumber > 0); err != nil { return err } - if err := statement.writeVersionIncrSet(w, v, w.Len() > previousLen); err != nil { + setNumber += len(statement.DecrColumns) + if err := statement.writeExprSets(w, setNumber > 0); err != nil { return err } + + setNumber += len(statement.ExprColumns) + if err := statement.writeVersionIncrSet(w, v, setNumber > 0); err != nil { + return err + } + + // if no columns to be updated, return error + if previousLen == w.Len() { + return ErrNoColumnsTobeUpdated + } return nil } var ErrNoColumnsTobeUpdated = errors.New("no columns found to be updated") -func (statement *Statement) WriteUpdate(updateWriter *builder.BytesWriter, cond builder.Cond, v reflect.Value, colNames []string, args []interface{}) error { +func (statement *Statement) WriteUpdate(updateWriter *builder.BytesWriter, cond builder.Cond, v reflect.Value, colNames []string, args []any) error { if _, err := fmt.Fprintf(updateWriter, "UPDATE"); err != nil { return err } @@ -591,21 +617,10 @@ func (statement *Statement) WriteUpdate(updateWriter *builder.BytesWriter, cond return err } - // write set - if _, err := fmt.Fprint(updateWriter, " SET "); err != nil { - return err - } - previousLen := updateWriter.Len() - if err := statement.writeUpdateSets(updateWriter, v, colNames, args); err != nil { return err } - // if no columns to be updated, return error - if previousLen == updateWriter.Len() { - return ErrNoColumnsTobeUpdated - } - // write from if err := statement.writeUpdateFrom(updateWriter); err != nil { return err diff --git a/internal/statements/values.go b/internal/statements/values.go index 4c1360ed..2bd0ed70 100644 --- a/internal/statements/values.go +++ b/internal/statements/values.go @@ -12,10 +12,10 @@ import ( "reflect" "time" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/json" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/json" + "xorm.io/xorm/v2/schemas" ) var ( @@ -24,7 +24,7 @@ var ( ) // Value2Interface convert a field value of a struct to interface for putting into database -func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) { +func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (any, error) { if fieldValue.CanAddr() { if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { data, err := fieldConvert.ToDB() diff --git a/internal/utils/builder.go b/internal/utils/builder.go index bc97526f..da7a6407 100644 --- a/internal/utils/builder.go +++ b/internal/utils/builder.go @@ -12,7 +12,7 @@ import ( type BuildReader interface { String() string - Args() []interface{} + Args() []any } // WriteBuilder writes writers to one diff --git a/internal/utils/reflect.go b/internal/utils/reflect.go index 7973d4d3..d2b4b3b8 100644 --- a/internal/utils/reflect.go +++ b/internal/utils/reflect.go @@ -9,6 +9,6 @@ import ( ) // ReflectValue returns value of a bean -func ReflectValue(bean interface{}) reflect.Value { +func ReflectValue(bean any) reflect.Value { return reflect.Indirect(reflect.ValueOf(bean)) } diff --git a/internal/utils/zero.go b/internal/utils/zero.go index 22c24071..1da63d95 100644 --- a/internal/utils/zero.go +++ b/internal/utils/zero.go @@ -17,7 +17,7 @@ type Zeroable interface { var nilTime *time.Time // IsZero returns false if k is nil or has a zero value -func IsZero(k interface{}) bool { +func IsZero(k any) bool { if k == nil { return true } diff --git a/internal/utils/zero_test.go b/internal/utils/zero_test.go index a5f4912a..8847cf2c 100644 --- a/internal/utils/zero_test.go +++ b/internal/utils/zero_test.go @@ -13,11 +13,13 @@ import ( "github.com/stretchr/testify/assert" ) -type MyInt int -type ZeroStruct struct{} +type ( + MyInt int + ZeroStruct struct{} +) func TestZero(t *testing.T) { - var zeroValues = []interface{}{ + zeroValues := []any{ int8(0), int16(0), int(0), @@ -46,7 +48,7 @@ func TestZero(t *testing.T) { } func TestIsValueZero(t *testing.T) { - var zeroReflectValues = []reflect.Value{ + zeroReflectValues := []reflect.Value{ reflect.ValueOf(int8(0)), reflect.ValueOf(int16(0)), reflect.ValueOf(int(0)), diff --git a/session_iterate.go b/iterate.go similarity index 78% rename from session_iterate.go rename to iterate.go index afb9a7cc..46b1a1f2 100644 --- a/session_iterate.go +++ b/iterate.go @@ -7,22 +7,22 @@ package xorm import ( "reflect" - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/internal/utils" ) // IterFunc only use by Iterate -type IterFunc func(idx int, bean interface{}) error +type IterFunc func(idx int, bean any) error // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields // are conditions. -func (session *Session) Rows(bean interface{}) (*Rows, error) { +func (session *Session) Rows(bean any) (*Rows, error) { return newRows(session, bean) } // Iterate record by record handle records from table, condiBeans's non-empty fields // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct -func (session *Session) Iterate(bean interface{}, fun IterFunc) error { +func (session *Session) Iterate(bean any, fun IterFunc) error { if session.isAutoClose { defer session.Close() } @@ -63,16 +63,16 @@ func (session *Session) BufferSize(size int) *Session { return session } -func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error { - var bufferSize = session.statement.BufferSize - var pLimitN = session.statement.LimitN +func (session *Session) bufferIterate(bean any, fun IterFunc) error { + bufferSize := session.statement.BufferSize + pLimitN := session.statement.LimitN if pLimitN != nil && bufferSize > *pLimitN { bufferSize = *pLimitN } - var start = session.statement.Start + start := session.statement.Start v := utils.ReflectValue(bean) sliceType := reflect.SliceOf(v.Type()) - var idx = 0 + idx := 0 session.autoResetStatement = false defer func() { session.autoResetStatement = true @@ -80,7 +80,7 @@ func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error { for bufferSize > 0 { slice := reflect.New(sliceType) - if err := session.NoCache().Limit(bufferSize, start).find(slice.Interface(), bean); err != nil { + if err := session.Limit(bufferSize, start).find(slice.Interface(), bean); err != nil { return err } diff --git a/log/logger.go b/log/logger.go index b8798c3f..0f3d3043 100644 --- a/log/logger.go +++ b/log/logger.go @@ -33,14 +33,14 @@ const ( // Logger is a logger interface type Logger interface { - Debug(v ...interface{}) - Debugf(format string, v ...interface{}) - Error(v ...interface{}) - Errorf(format string, v ...interface{}) - Info(v ...interface{}) - Infof(format string, v ...interface{}) - Warn(v ...interface{}) - Warnf(format string, v ...interface{}) + Debug(v ...any) + Debugf(format string, v ...any) + Error(v ...any) + Errorf(format string, v ...any) + Info(v ...any) + Infof(format string, v ...any) + Warn(v ...any) + Warnf(format string, v ...any) Level() LogLevel SetLevel(l LogLevel) @@ -55,28 +55,28 @@ var _ Logger = DiscardLogger{} type DiscardLogger struct{} // Debug empty implementation -func (DiscardLogger) Debug(v ...interface{}) {} +func (DiscardLogger) Debug(v ...any) {} // Debugf empty implementation -func (DiscardLogger) Debugf(format string, v ...interface{}) {} +func (DiscardLogger) Debugf(format string, v ...any) {} // Error empty implementation -func (DiscardLogger) Error(v ...interface{}) {} +func (DiscardLogger) Error(v ...any) {} // Errorf empty implementation -func (DiscardLogger) Errorf(format string, v ...interface{}) {} +func (DiscardLogger) Errorf(format string, v ...any) {} // Info empty implementation -func (DiscardLogger) Info(v ...interface{}) {} +func (DiscardLogger) Info(v ...any) {} // Infof empty implementation -func (DiscardLogger) Infof(format string, v ...interface{}) {} +func (DiscardLogger) Infof(format string, v ...any) {} // Warn empty implementation -func (DiscardLogger) Warn(v ...interface{}) {} +func (DiscardLogger) Warn(v ...any) {} // Warnf empty implementation -func (DiscardLogger) Warnf(format string, v ...interface{}) {} +func (DiscardLogger) Warnf(format string, v ...any) {} // Level empty implementation func (DiscardLogger) Level() LogLevel { @@ -128,56 +128,56 @@ func NewSimpleLogger3(out io.Writer, prefix string, flag int, l LogLevel) *Simpl } // Error implement ILogger -func (s *SimpleLogger) Error(v ...interface{}) { +func (s *SimpleLogger) Error(v ...any) { if s.level <= LOG_ERR { _ = s.ERR.Output(2, fmt.Sprintln(v...)) } } // Errorf implement ILogger -func (s *SimpleLogger) Errorf(format string, v ...interface{}) { +func (s *SimpleLogger) Errorf(format string, v ...any) { if s.level <= LOG_ERR { _ = s.ERR.Output(2, fmt.Sprintf(format, v...)) } } // Debug implement ILogger -func (s *SimpleLogger) Debug(v ...interface{}) { +func (s *SimpleLogger) Debug(v ...any) { if s.level <= LOG_DEBUG { _ = s.DEBUG.Output(2, fmt.Sprintln(v...)) } } // Debugf implement ILogger -func (s *SimpleLogger) Debugf(format string, v ...interface{}) { +func (s *SimpleLogger) Debugf(format string, v ...any) { if s.level <= LOG_DEBUG { _ = s.DEBUG.Output(2, fmt.Sprintf(format, v...)) } } // Info implement ILogger -func (s *SimpleLogger) Info(v ...interface{}) { +func (s *SimpleLogger) Info(v ...any) { if s.level <= LOG_INFO { _ = s.INFO.Output(2, fmt.Sprintln(v...)) } } // Infof implement ILogger -func (s *SimpleLogger) Infof(format string, v ...interface{}) { +func (s *SimpleLogger) Infof(format string, v ...any) { if s.level <= LOG_INFO { _ = s.INFO.Output(2, fmt.Sprintf(format, v...)) } } // Warn implement ILogger -func (s *SimpleLogger) Warn(v ...interface{}) { +func (s *SimpleLogger) Warn(v ...any) { if s.level <= LOG_WARNING { _ = s.WARN.Output(2, fmt.Sprintln(v...)) } } // Warnf implement ILogger -func (s *SimpleLogger) Warnf(format string, v ...interface{}) { +func (s *SimpleLogger) Warnf(format string, v ...any) { if s.level <= LOG_WARNING { _ = s.WARN.Output(2, fmt.Sprintf(format, v...)) } diff --git a/log/logger_context.go b/log/logger_context.go index 46802576..c734125e 100644 --- a/log/logger_context.go +++ b/log/logger_context.go @@ -7,7 +7,7 @@ package log import ( "fmt" - "xorm.io/xorm/contexts" + "xorm.io/xorm/v2/contexts" ) // LogContext represents a log context @@ -23,10 +23,10 @@ type SQLLogger interface { type ContextLogger interface { SQLLogger - Debugf(format string, v ...interface{}) - Errorf(format string, v ...interface{}) - Infof(format string, v ...interface{}) - Warnf(format string, v ...interface{}) + Debugf(format string, v ...any) + Errorf(format string, v ...any) + Infof(format string, v ...any) + Warnf(format string, v ...any) Level() LogLevel SetLevel(l LogLevel) @@ -35,9 +35,7 @@ type ContextLogger interface { IsShowSQL() bool } -var ( - _ ContextLogger = &LoggerAdapter{} -) +var _ ContextLogger = &LoggerAdapter{} // enumerate all the context keys var ( @@ -76,22 +74,22 @@ func (l *LoggerAdapter) AfterSQL(ctx LogContext) { } // Debugf implements ContextLogger -func (l *LoggerAdapter) Debugf(format string, v ...interface{}) { +func (l *LoggerAdapter) Debugf(format string, v ...any) { l.logger.Debugf(format, v...) } // Errorf implements ContextLogger -func (l *LoggerAdapter) Errorf(format string, v ...interface{}) { +func (l *LoggerAdapter) Errorf(format string, v ...any) { l.logger.Errorf(format, v...) } // Infof implements ContextLogger -func (l *LoggerAdapter) Infof(format string, v ...interface{}) { +func (l *LoggerAdapter) Infof(format string, v ...any) { l.logger.Infof(format, v...) } // Warnf implements ContextLogger -func (l *LoggerAdapter) Warnf(format string, v ...interface{}) { +func (l *LoggerAdapter) Warnf(format string, v ...any) { l.logger.Warnf(format, v...) } diff --git a/log/syslogger.go b/log/syslogger.go index 44272586..2c1bd399 100644 --- a/log/syslogger.go +++ b/log/syslogger.go @@ -26,42 +26,42 @@ func NewSyslogLogger(w *syslog.Writer) *SyslogLogger { } // Debug log content as Debug -func (s *SyslogLogger) Debug(v ...interface{}) { +func (s *SyslogLogger) Debug(v ...any) { _ = s.w.Debug(fmt.Sprint(v...)) } // Debugf log content as Debug and format -func (s *SyslogLogger) Debugf(format string, v ...interface{}) { +func (s *SyslogLogger) Debugf(format string, v ...any) { _ = s.w.Debug(fmt.Sprintf(format, v...)) } // Error log content as Error -func (s *SyslogLogger) Error(v ...interface{}) { +func (s *SyslogLogger) Error(v ...any) { _ = s.w.Err(fmt.Sprint(v...)) } // Errorf log content as Errorf and format -func (s *SyslogLogger) Errorf(format string, v ...interface{}) { +func (s *SyslogLogger) Errorf(format string, v ...any) { _ = s.w.Err(fmt.Sprintf(format, v...)) } // Info log content as Info -func (s *SyslogLogger) Info(v ...interface{}) { +func (s *SyslogLogger) Info(v ...any) { _ = s.w.Info(fmt.Sprint(v...)) } // Infof log content as Infof and format -func (s *SyslogLogger) Infof(format string, v ...interface{}) { +func (s *SyslogLogger) Infof(format string, v ...any) { _ = s.w.Info(fmt.Sprintf(format, v...)) } // Warn log content as Warn -func (s *SyslogLogger) Warn(v ...interface{}) { +func (s *SyslogLogger) Warn(v ...any) { _ = s.w.Warning(fmt.Sprint(v...)) } // Warnf log content as Warnf and format -func (s *SyslogLogger) Warnf(format string, v ...interface{}) { +func (s *SyslogLogger) Warnf(format string, v ...any) { _ = s.w.Warning(fmt.Sprintf(format, v...)) } diff --git a/processors.go b/processors.go index 8697e302..938c0781 100644 --- a/processors.go +++ b/processors.go @@ -54,12 +54,12 @@ type AfterLoadSessionProcessor interface { AfterLoad(*Session) } -type executedProcessorFunc func(*Session, interface{}) error +type executedProcessorFunc func(*Session, any) error type executedProcessor struct { fun executedProcessorFunc session *Session - bean interface{} + bean any } func (executor *executedProcessor) execute() error { @@ -77,13 +77,13 @@ func (session *Session) executeProcessors() error { return nil } -func cleanupProcessorsClosures(slices *[]func(interface{})) { +func cleanupProcessorsClosures(slices *[]func(any)) { if len(*slices) > 0 { - *slices = make([]func(interface{}), 0) + *slices = make([]func(any), 0) } } -func executeBeforeClosures(session *Session, bean interface{}) { +func executeBeforeClosures(session *Session, bean any) { // handle before delete processors for _, closure := range session.beforeClosures { closure(bean) @@ -91,27 +91,27 @@ func executeBeforeClosures(session *Session, bean interface{}) { cleanupProcessorsClosures(&session.beforeClosures) } -func executeBeforeSet(bean interface{}, fields []string, scanResults []interface{}) { +func executeBeforeSet(bean any, fields []string, scanResults []any) { if b, hasBeforeSet := bean.(BeforeSetProcessor); hasBeforeSet { for ii, key := range fields { - b.BeforeSet(key, Cell(scanResults[ii].(*interface{}))) + b.BeforeSet(key, Cell(scanResults[ii].(*any))) } } } -func executeAfterSet(bean interface{}, fields []string, scanResults []interface{}) { +func executeAfterSet(bean any, fields []string, scanResults []any) { if b, hasAfterSet := bean.(AfterSetProcessor); hasAfterSet { for ii, key := range fields { - b.AfterSet(key, Cell(scanResults[ii].(*interface{}))) + b.AfterSet(key, Cell(scanResults[ii].(*any))) } } } -func buildAfterProcessors(session *Session, bean interface{}) { +func buildAfterProcessors(session *Session, bean any) { // handle afterClosures for _, closure := range session.afterClosures { session.afterProcessors = append(session.afterProcessors, executedProcessor{ - fun: func(sess *Session, bean interface{}) error { + fun: func(sess *Session, bean any) error { closure(bean) return nil }, @@ -122,7 +122,7 @@ func buildAfterProcessors(session *Session, bean interface{}) { if a, has := bean.(AfterLoadProcessor); has { session.afterProcessors = append(session.afterProcessors, executedProcessor{ - fun: func(sess *Session, bean interface{}) error { + fun: func(sess *Session, bean any) error { a.AfterLoad() return nil }, @@ -133,7 +133,7 @@ func buildAfterProcessors(session *Session, bean interface{}) { if a, has := bean.(AfterLoadSessionProcessor); has { session.afterProcessors = append(session.afterProcessors, executedProcessor{ - fun: func(sess *Session, bean interface{}) error { + fun: func(sess *Session, bean any) error { a.AfterLoad(sess) return nil }, diff --git a/session_raw.go b/raw.go similarity index 79% rename from session_raw.go rename to raw.go index 99f6be99..3ac8da42 100644 --- a/session_raw.go +++ b/raw.go @@ -8,10 +8,10 @@ import ( "database/sql" "strings" - "xorm.io/xorm/core" + "xorm.io/xorm/v2/internal/core" ) -func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) { +func (session *Session) queryPreprocess(sqlStr *string, paramStr ...any) { for _, filter := range session.engine.dialect.Filters() { *sqlStr = filter.Do(session.ctx, *sqlStr) } @@ -20,7 +20,7 @@ func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) session.lastSQLArgs = paramStr } -func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Rows, error) { +func (session *Session) queryRows(sqlStr string, args ...any) (*core.Rows, error) { defer session.resetStatement() if session.statement.LastError != nil { return nil, session.statement.LastError @@ -34,9 +34,9 @@ func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Row if session.isAutoCommit { var db *core.DB if session.sessionType == groupSession && strings.EqualFold(strings.TrimSpace(sqlStr)[:6], "select") && !session.statement.IsForUpdate { - db = session.engine.engineGroup.Slave().DB() + db = session.engine.engineGroup.Slave().db } else { - db = session.DB() + db = session.db() } if session.prepareStmt { @@ -64,12 +64,12 @@ func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Row return session.tx.QueryContext(session.ctx, sqlStr, args...) } -func (session *Session) queryRow(sqlStr string, args ...interface{}) *core.Row { +func (session *Session) queryRow(sqlStr string, args ...any) *core.Row { return core.NewRow(session.queryRows(sqlStr, args...)) } // Query runs a raw sql and return records as []map[string][]byte -func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) { +func (session *Session) Query(sqlOrArgs ...any) ([]map[string][]byte, error) { if session.isAutoClose { defer session.Close() } @@ -89,7 +89,7 @@ func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, er } // QueryString runs a raw sql and return records as []map[string]string -func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) { +func (session *Session) QueryString(sqlOrArgs ...any) ([]map[string]string, error) { if session.isAutoClose { defer session.Close() } @@ -109,7 +109,7 @@ func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]stri } // QuerySliceString runs a raw sql and return records as [][]string -func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, error) { +func (session *Session) QuerySliceString(sqlOrArgs ...any) ([][]string, error) { if session.isAutoClose { defer session.Close() } @@ -128,8 +128,8 @@ func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, return session.engine.ScanStringSlices(rows) } -// QueryInterface runs a raw sql and return records as []map[string]interface{} -func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) { +// QueryInterface runs a raw sql and return records as []map[string]any +func (session *Session) QueryInterface(sqlOrArgs ...any) ([]map[string]any, error) { if session.isAutoClose { defer session.Close() } @@ -148,7 +148,7 @@ func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]i return session.engine.ScanInterfaceMaps(rows) } -func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) { +func (session *Session) exec(sqlStr string, args ...any) (sql.Result, error) { defer session.resetStatement() session.queryPreprocess(&sqlStr, args...) @@ -168,18 +168,18 @@ func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, er } if session.prepareStmt { - stmt, err := session.doPrepare(session.DB(), sqlStr) + stmt, err := session.doPrepare(session.db(), sqlStr) if err != nil { return nil, err } return stmt.ExecContext(session.ctx, args...) } - return session.DB().ExecContext(session.ctx, sqlStr, args...) + return session.db().ExecContext(session.ctx, sqlStr, args...) } // Exec raw sql -func (session *Session) Exec(sqlOrArgs ...interface{}) (sql.Result, error) { +func (session *Session) Exec(sqlOrArgs ...any) (sql.Result, error) { if session.isAutoClose { defer session.Close() } diff --git a/rows.go b/rows.go index c539410e..eed39d18 100644 --- a/rows.go +++ b/rows.go @@ -10,7 +10,7 @@ import ( "reflect" "xorm.io/builder" - "xorm.io/xorm/core" + "xorm.io/xorm/v2/internal/core" ) // Rows rows wrapper a rows to @@ -20,13 +20,13 @@ type Rows struct { beanType reflect.Type } -func newRows(session *Session, bean interface{}) (*Rows, error) { +func newRows(session *Session, bean any) (*Rows, error) { rows := new(Rows) rows.session = session rows.beanType = reflect.Indirect(reflect.ValueOf(bean)).Type() var sqlStr string - var args []interface{} + var args []any var err error beanValue := reflect.ValueOf(bean) @@ -98,7 +98,7 @@ func (rows *Rows) Err() error { } // Scan row record to bean properties -func (rows *Rows) Scan(beans ...interface{}) error { +func (rows *Rows) Scan(beans ...any) error { if rows.Err() != nil { return rows.Err() } diff --git a/scan.go b/scan.go index 00cee4d7..00c924c7 100644 --- a/scan.go +++ b/scan.go @@ -11,16 +11,16 @@ import ( "reflect" "time" - "xorm.io/xorm/convert" - "xorm.io/xorm/core" - "xorm.io/xorm/dialects" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/schemas" ) // genScanResultsByBeanNullabale generates scan result -func genScanResultsByBeanNullable(bean interface{}) (interface{}, bool, error) { +func genScanResultsByBeanNullable(bean any) (any, bool, error) { switch t := bean.(type) { - case *interface{}: + case *any: return t, false, nil case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString, *sql.RawBytes, *[]byte: return t, false, nil @@ -71,9 +71,9 @@ func genScanResultsByBeanNullable(bean interface{}) (interface{}, bool, error) { } } -func genScanResultsByBean(bean interface{}) (interface{}, bool, error) { +func genScanResultsByBean(bean any) (any, bool, error) { switch t := bean.(type) { - case *interface{}: + case *any: return t, false, nil case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString, *sql.RawBytes, @@ -129,8 +129,8 @@ func genScanResultsByBean(bean interface{}) (interface{}, bool, error) { } } -func (engine *Engine) scanStringInterface(rows *core.Rows, fields []string, types []*sql.ColumnType) ([]interface{}, error) { - scanResults := make([]interface{}, len(types)) +func (engine *Engine) scanStringInterface(rows *core.Rows, fields []string, types []*sql.ColumnType) ([]any, error) { + scanResults := make([]any, len(types)) for i := 0; i < len(types); i++ { var s sql.NullString scanResults[i] = &s @@ -143,13 +143,13 @@ func (engine *Engine) scanStringInterface(rows *core.Rows, fields []string, type } // scan is a wrap of driver.Scan but will automatically change the input values according requirements -func (engine *Engine) scan(rows *core.Rows, fields []string, types []*sql.ColumnType, vv ...interface{}) error { - scanResults := make([]interface{}, 0, len(types)) +func (engine *Engine) scan(rows *core.Rows, fields []string, types []*sql.ColumnType, vv ...any) error { + scanResults := make([]any, 0, len(types)) replaces := make([]bool, 0, len(types)) var err error for _, v := range vv { var replaced bool - var scanResult interface{} + var scanResult any switch t := v.(type) { case *big.Float, *time.Time, *sql.NullTime: scanResult = &sql.NullString{} @@ -193,8 +193,8 @@ func (engine *Engine) scan(rows *core.Rows, fields []string, types []*sql.Column return nil } -func (engine *Engine) scanInterfaces(rows *core.Rows, fields []string, types []*sql.ColumnType) ([]interface{}, error) { - scanResultContainers := make([]interface{}, len(types)) +func (engine *Engine) scanInterfaces(rows *core.Rows, fields []string, types []*sql.ColumnType) ([]any, error) { + scanResultContainers := make([]any, len(types)) for i := 0; i < len(types); i++ { scanResult, err := engine.driver.GenScanResult(types[i].DatabaseTypeName()) if err != nil { @@ -209,11 +209,11 @@ func (engine *Engine) scanInterfaces(rows *core.Rows, fields []string, types []* } //////////////////// -// row -> map[string]interface{} +// row -> map[string]any -func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]interface{}, error) { - resultsMap := make(map[string]interface{}, len(fields)) - scanResultContainers := make([]interface{}, len(fields)) +func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]any, error) { + resultsMap := make(map[string]any, len(fields)) + scanResultContainers := make([]any, len(fields)) for i := 0; i < len(fields); i++ { scanResult, err := engine.driver.GenScanResult(types[i].DatabaseTypeName()) if err != nil { @@ -236,7 +236,7 @@ func (engine *Engine) row2mapInterface(rows *core.Rows, types []*sql.ColumnType, } // ScanInterfaceMap scan result from *core.Rows and return a map -func (engine *Engine) ScanInterfaceMap(rows *core.Rows) (map[string]interface{}, error) { +func (engine *Engine) ScanInterfaceMap(rows *core.Rows) (map[string]any, error) { fields, err := rows.Columns() if err != nil { return nil, err @@ -250,7 +250,7 @@ func (engine *Engine) ScanInterfaceMap(rows *core.Rows) (map[string]interface{}, } // ScanInterfaceMaps scan results from *core.Rows and return a slice of map -func (engine *Engine) ScanInterfaceMaps(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) { +func (engine *Engine) ScanInterfaceMaps(rows *core.Rows) (resultsSlice []map[string]any, err error) { fields, err := rows.Columns() if err != nil { return nil, err @@ -277,7 +277,7 @@ func (engine *Engine) ScanInterfaceMaps(rows *core.Rows) (resultsSlice []map[str // row -> map[string]string func (engine *Engine) row2mapStr(rows *core.Rows, types []*sql.ColumnType, fields []string) (map[string]string, error) { - scanResults := make([]interface{}, len(fields)) + scanResults := make([]any, len(fields)) for i := 0; i < len(fields); i++ { var s sql.NullString scanResults[i] = &s diff --git a/session_schema.go b/schema.go similarity index 85% rename from session_schema.go rename to schema.go index 830ba08a..b3ede83a 100644 --- a/session_schema.go +++ b/schema.go @@ -13,8 +13,8 @@ import ( "os" "strings" - "xorm.io/xorm/dialects" - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/utils" ) // Ping test if database is ok @@ -24,11 +24,11 @@ func (session *Session) Ping() error { } session.engine.logger.Infof("PING DATABASE %v", session.engine.DriverName()) - return session.DB().PingContext(session.ctx) + return session.db().PingContext(session.ctx) } // CreateTable create a table according a bean -func (session *Session) CreateTable(bean interface{}) error { +func (session *Session) CreateTable(bean any) error { if session.isAutoClose { defer session.Close() } @@ -36,7 +36,7 @@ func (session *Session) CreateTable(bean interface{}) error { return session.createTable(bean) } -func (session *Session) createTable(bean interface{}) error { +func (session *Session) createTable(bean any) error { if err := session.statement.SetRefBean(bean); err != nil { return err } @@ -67,7 +67,7 @@ func (session *Session) createTable(bean interface{}) error { } // CreateIndexes create indexes -func (session *Session) CreateIndexes(bean interface{}) error { +func (session *Session) CreateIndexes(bean any) error { if session.isAutoClose { defer session.Close() } @@ -75,7 +75,7 @@ func (session *Session) CreateIndexes(bean interface{}) error { return session.createIndexes(bean) } -func (session *Session) createIndexes(bean interface{}) error { +func (session *Session) createIndexes(bean any) error { if err := session.statement.SetRefBean(bean); err != nil { return err } @@ -91,14 +91,14 @@ func (session *Session) createIndexes(bean interface{}) error { } // CreateUniques create uniques -func (session *Session) CreateUniques(bean interface{}) error { +func (session *Session) CreateUniques(bean any) error { if session.isAutoClose { defer session.Close() } return session.createUniques(bean) } -func (session *Session) createUniques(bean interface{}) error { +func (session *Session) createUniques(bean any) error { if err := session.statement.SetRefBean(bean); err != nil { return err } @@ -114,7 +114,7 @@ func (session *Session) createUniques(bean interface{}) error { } // DropIndexes drop indexes -func (session *Session) DropIndexes(bean interface{}) error { +func (session *Session) DropIndexes(bean any) error { if session.isAutoClose { defer session.Close() } @@ -122,7 +122,7 @@ func (session *Session) DropIndexes(bean interface{}) error { return session.dropIndexes(bean) } -func (session *Session) dropIndexes(bean interface{}) error { +func (session *Session) dropIndexes(bean any) error { if err := session.statement.SetRefBean(bean); err != nil { return err } @@ -138,7 +138,7 @@ func (session *Session) dropIndexes(bean interface{}) error { } // DropTable drop table will drop table if exist, if drop failed, it will return error -func (session *Session) DropTable(beanOrTableName interface{}) error { +func (session *Session) DropTable(beanOrTableName any) error { if session.isAutoClose { defer session.Close() } @@ -146,11 +146,11 @@ func (session *Session) DropTable(beanOrTableName interface{}) error { return session.dropTable(beanOrTableName) } -func (session *Session) dropTable(beanOrTableName interface{}) error { +func (session *Session) dropTable(beanOrTableName any) error { tableName := session.engine.TableName(beanOrTableName) sqlStr, checkIfExist := session.engine.dialect.DropTableSQL(session.engine.TableName(tableName, true)) if !checkIfExist { - exist, err := session.engine.dialect.IsTableExist(session.getQueryer(), session.ctx, tableName) + exist, err := session.engine.dialect.IsTableExist(session.ctx, session.getQueryer(), tableName) if err != nil { return err } @@ -186,7 +186,7 @@ func (session *Session) dropTable(beanOrTableName interface{}) error { } // IsTableExist if a table is exist -func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) { +func (session *Session) IsTableExist(beanOrTableName any) (bool, error) { if session.isAutoClose { defer session.Close() } @@ -197,11 +197,11 @@ func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) } func (session *Session) isTableExist(tableName string) (bool, error) { - return session.engine.dialect.IsTableExist(session.getQueryer(), session.ctx, tableName) + return session.engine.dialect.IsTableExist(session.ctx, session.getQueryer(), tableName) } // IsTableEmpty if table have any records -func (session *Session) IsTableEmpty(bean interface{}) (bool, error) { +func (session *Session) IsTableEmpty(bean any) (bool, error) { if session.isAutoClose { defer session.Close() } diff --git a/schemas/column.go b/schemas/column.go index 08d34b91..5153685b 100644 --- a/schemas/column.go +++ b/schemas/column.go @@ -76,7 +76,7 @@ func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int64, nullab } // ValueOf returns column's filed of struct's value -func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) { +func (col *Column) ValueOf(bean any) (*reflect.Value, error) { dataStruct := reflect.Indirect(reflect.ValueOf(bean)) return col.ValueOfV(&dataStruct) } @@ -99,7 +99,7 @@ func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) { } // ConvertID converts id content to suitable type according column type -func (col *Column) ConvertID(sid string) (interface{}, error) { +func (col *Column) ConvertID(sid string) (any, error) { if col.SQLType.IsNumeric() { n, err := strconv.ParseInt(sid, 10, 64) if err != nil { diff --git a/schemas/pk.go b/schemas/pk.go index da3c7899..83a05923 100644 --- a/schemas/pk.go +++ b/schemas/pk.go @@ -8,14 +8,14 @@ import ( "bytes" "encoding/gob" - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/internal/utils" ) // PK represents primary key values -type PK []interface{} +type PK []any // NewPK creates primay keys -func NewPK(pks ...interface{}) *PK { +func NewPK(pks ...any) *PK { p := PK(pks) return &p } diff --git a/schemas/table.go b/schemas/table.go index 5c38cc70..be19127b 100644 --- a/schemas/table.go +++ b/schemas/table.go @@ -156,7 +156,7 @@ func (table *Table) AddIndex(index *Index) { // IDOfV get id from one value of struct func (table *Table) IDOfV(rv reflect.Value) (PK, error) { v := reflect.Indirect(rv) - pk := make([]interface{}, len(table.PrimaryKeys)) + pk := make([]any, len(table.PrimaryKeys)) for i, col := range table.PKColumns() { var err error diff --git a/session.go b/session.go index 14d0781e..42616287 100644 --- a/session.go +++ b/session.go @@ -15,14 +15,14 @@ import ( "hash/crc32" "io" "reflect" - "strconv" - "xorm.io/xorm/contexts" - "xorm.io/xorm/convert" - "xorm.io/xorm/core" - "xorm.io/xorm/internal/json" - "xorm.io/xorm/internal/statements" - "xorm.io/xorm/log" - "xorm.io/xorm/schemas" + + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/core" + "xorm.io/xorm/v2/internal/json" + "xorm.io/xorm/v2/internal/statements" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/schemas" ) // ErrFieldIsNotExist columns does not exist @@ -68,20 +68,20 @@ type Session struct { autoResetStatement bool // !nashtsai! storing these beans due to yet committed tx - afterInsertBeans map[interface{}]*[]func(interface{}) - afterUpdateBeans map[interface{}]*[]func(interface{}) - afterDeleteBeans map[interface{}]*[]func(interface{}) + afterInsertBeans map[any]*[]func(any) + afterUpdateBeans map[any]*[]func(any) + afterDeleteBeans map[any]*[]func(any) // -- - beforeClosures []func(interface{}) - afterClosures []func(interface{}) + beforeClosures []func(any) + afterClosures []func(any) afterProcessors []executedProcessor stmtCache map[uint32]*core.Stmt // key: hash.Hash32 of (queryStr, len(queryStr)) txStmtCache map[uint32]*core.Stmt // for tx statement lastSQL string - lastSQLArgs []interface{} + lastSQLArgs []any ctx context.Context sessionType sessionType @@ -122,17 +122,17 @@ func newSession(engine *Engine) *Session { autoResetStatement: true, prepareStmt: false, - afterInsertBeans: make(map[interface{}]*[]func(interface{})), - afterUpdateBeans: make(map[interface{}]*[]func(interface{})), - afterDeleteBeans: make(map[interface{}]*[]func(interface{})), - beforeClosures: make([]func(interface{}), 0), - afterClosures: make([]func(interface{}), 0), + afterInsertBeans: make(map[any]*[]func(any)), + afterUpdateBeans: make(map[any]*[]func(any)), + afterDeleteBeans: make(map[any]*[]func(any)), + beforeClosures: make([]func(any), 0), + afterClosures: make([]func(any), 0), afterProcessors: make([]executedProcessor, 0), stmtCache: make(map[uint32]*core.Stmt), txStmtCache: make(map[uint32]*core.Stmt), lastSQL: "", - lastSQLArgs: make([]interface{}, 0), + lastSQLArgs: make([]any, 0), sessionType: engineSession, } @@ -218,7 +218,7 @@ func (session *Session) Prepare() *Session { } // Before Apply before Processor, affected bean is passed to closure arg -func (session *Session) Before(closures func(interface{})) *Session { +func (session *Session) Before(closures func(any)) *Session { if closures != nil { session.beforeClosures = append(session.beforeClosures, closures) } @@ -226,7 +226,7 @@ func (session *Session) Before(closures func(interface{})) *Session { } // After Apply after Processor, affected bean is passed to closure arg -func (session *Session) After(closures func(interface{})) *Session { +func (session *Session) After(closures func(any)) *Session { if closures != nil { session.afterClosures = append(session.afterClosures, closures) } @@ -234,7 +234,7 @@ func (session *Session) After(closures func(interface{})) *Session { } // Table can input a string or pointer to struct for special a table to operate. -func (session *Session) Table(tableNameOrBean interface{}) *Session { +func (session *Session) Table(tableNameOrBean any) *Session { if err := session.statement.SetTable(tableNameOrBean); err != nil { session.statement.LastError = err } @@ -273,7 +273,7 @@ func (session *Session) Limit(limit int, start ...int) *Session { // OrderBy provide order by query condition, the input parameter is the content // after order by on a sql statement. -func (session *Session) OrderBy(order interface{}, args ...interface{}) *Session { +func (session *Session) OrderBy(order any, args ...any) *Session { session.statement.OrderBy(order, args...) return session } @@ -320,15 +320,8 @@ func (session *Session) MustLogSQL(logs ...bool) *Session { return session } -// NoCache ask this session do not retrieve data from cache system and -// get data from database directly. -func (session *Session) NoCache() *Session { - session.statement.UseCache = false - return session -} - // Join join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN -func (session *Session) Join(joinOperator string, tablename interface{}, condition interface{}, args ...interface{}) *Session { +func (session *Session) Join(joinOperator string, tablename any, condition any, args ...any) *Session { session.statement.Join(joinOperator, tablename, condition, args...) return session } @@ -345,24 +338,6 @@ func (session *Session) Having(conditions string) *Session { return session } -// DB db return the wrapper of sql.DB -func (session *Session) DB() *core.DB { - return session.db() -} - -func (session *Session) canCache() bool { - if session.statement.RefTable == nil || - session.statement.NeedTableName() || - session.statement.RawSQL != "" || - !session.statement.UseCache || - session.statement.IsForUpdate || - session.tx != nil || - len(session.statement.SelectStr) > 0 { - return false - } - return true -} - func (session *Session) doPrepare(db *core.DB, sqlStr string) (stmt *core.Stmt, err error) { crc := crc32.ChecksumIEEE([]byte(sqlStr)) // TODO try hash(sqlStr+len(sqlStr)) @@ -378,21 +353,6 @@ func (session *Session) doPrepare(db *core.DB, sqlStr string) (stmt *core.Stmt, return } -func (session *Session) doPrepareTx(sqlStr string) (stmt *core.Stmt, err error) { - crc := crc32.ChecksumIEEE([]byte(sqlStr)) - // TODO try hash(sqlStr+len(sqlStr)) - var has bool - stmt, has = session.txStmtCache[crc] - if !has { - stmt, err = session.tx.PrepareContext(session.ctx, sqlStr) - if err != nil { - return nil, err - } - session.txStmtCache[crc] = stmt - } - return -} - func getField(dataStruct *reflect.Value, table *schemas.Table, field *QueryedField) (*schemas.Column, *reflect.Value, error) { col := field.ColumnSchema if col == nil { @@ -414,7 +374,7 @@ func getField(dataStruct *reflect.Value, table *schemas.Table, field *QueryedFie } // Cell cell is a result of one column field -type Cell *interface{} +type Cell *any func (session *Session) rows2Beans(rows *core.Rows, columnsSchema *ColumnsSchema, fields []string, types []*sql.ColumnType, table *schemas.Table, newElemFunc func([]string) reflect.Value, @@ -435,7 +395,7 @@ func (session *Session) rows2Beans(rows *core.Rows, columnsSchema *ColumnsSchema return err } session.afterProcessors = append(session.afterProcessors, executedProcessor{ - fun: func(*Session, interface{}) error { + fun: func(*Session, any) error { return sliceValueSetFunc(&newValue, pk) }, session: session, @@ -445,14 +405,14 @@ func (session *Session) rows2Beans(rows *core.Rows, columnsSchema *ColumnsSchema return rows.Err() } -func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql.ColumnType, bean interface{}) ([]interface{}, error) { +func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql.ColumnType, bean any) ([]any, error) { for _, closure := range session.beforeClosures { closure(bean) } - scanResults := make([]interface{}, len(fields)) + scanResults := make([]any, len(fields)) for i := 0; i < len(fields); i++ { - var cell interface{} + var cell any scanResults[i] = &cell } if err := session.engine.scan(rows, fields, types, scanResults...); err != nil { @@ -464,7 +424,7 @@ func (session *Session) row2Slice(rows *core.Rows, fields []string, types []*sql return scanResults, nil } -func setJSON(fieldValue *reflect.Value, fieldType reflect.Type, scanResult interface{}) error { +func setJSON(fieldValue *reflect.Value, fieldType reflect.Type, scanResult any) error { bs, ok := convert.AsBytes(scanResult) if !ok { return fmt.Errorf("unsupported database data type: %#v", scanResult) @@ -494,50 +454,12 @@ func setJSON(fieldValue *reflect.Value, fieldType reflect.Type, scanResult inter return nil } -func asKind(vv reflect.Value, tp reflect.Type) (interface{}, error) { - switch tp.Kind() { - case reflect.Ptr: - return asKind(vv.Elem(), tp.Elem()) - case reflect.Int64: - return vv.Int(), nil - case reflect.Int: - return int(vv.Int()), nil - case reflect.Int32: - return int32(vv.Int()), nil - case reflect.Int16: - return int16(vv.Int()), nil - case reflect.Int8: - return int8(vv.Int()), nil - case reflect.Uint64: - return vv.Uint(), nil - case reflect.Uint: - return uint(vv.Uint()), nil - case reflect.Uint32: - return uint32(vv.Uint()), nil - case reflect.Uint16: - return uint16(vv.Uint()), nil - case reflect.Uint8: - return uint8(vv.Uint()), nil - case reflect.String: - return vv.String(), nil - case reflect.Slice: - if tp.Elem().Kind() == reflect.Uint8 { - v, err := strconv.ParseInt(string(vv.Interface().([]byte)), 10, 64) - if err != nil { - return nil, err - } - return v, nil - } - } - return nil, fmt.Errorf("unsupported primary key type: %v, %v", tp, vv) -} - var uint8ZeroValue = reflect.ValueOf(uint8(0)) func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflect.Value, - scanResult interface{}, table *schemas.Table, + scanResult any, table *schemas.Table, ) error { - v, ok := scanResult.(*interface{}) + v, ok := scanResult.(*any) if ok { scanResult = *v } @@ -676,7 +598,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec return errors.New("unsupported non or composited primary key cascade") } pk := make(schemas.PK, len(table.PrimaryKeys)) - pk[0], err = asKind(vv, reflect.TypeOf(scanResult)) + pk[0], err = convert.AsKind(vv, reflect.TypeOf(scanResult)) if err != nil { return err } @@ -703,7 +625,7 @@ func (session *Session) convertBeanField(col *schemas.Column, fieldValue *reflec return convert.AssignValue(fieldValue.Addr(), scanResult) } -func (session *Session) slice2Bean(scanResults []interface{}, columnsSchema *ColumnsSchema, fields []string, bean interface{}, dataStruct *reflect.Value, table *schemas.Table) (schemas.PK, error) { +func (session *Session) slice2Bean(scanResults []any, columnsSchema *ColumnsSchema, fields []string, bean any, dataStruct *reflect.Value, table *schemas.Table) (schemas.PK, error) { defer func() { executeAfterSet(bean, fields, scanResults) }() @@ -734,13 +656,13 @@ func (session *Session) slice2Bean(scanResults []interface{}, columnsSchema *Col } // saveLastSQL stores executed query information -func (session *Session) saveLastSQL(sql string, args ...interface{}) { +func (session *Session) saveLastSQL(sql string, args ...any) { session.lastSQL = sql session.lastSQLArgs = args } // LastSQL returns last query information -func (session *Session) LastSQL() (string, []interface{}) { +func (session *Session) LastSQL() (string, []any) { return session.lastSQL, session.lastSQLArgs } @@ -778,7 +700,7 @@ func (session *Session) PingContext(ctx context.Context) error { } session.engine.logger.Infof("PING DATABASE %v", session.engine.DriverName()) - return session.DB().PingContext(ctx) + return session.db().PingContext(ctx) } // disable version check diff --git a/session_delete.go b/session_delete.go deleted file mode 100644 index 7336040f..00000000 --- a/session_delete.go +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright 2016 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package xorm - -import ( - "errors" - "strconv" - - "xorm.io/builder" - "xorm.io/xorm/caches" - "xorm.io/xorm/schemas" -) - -// ErrNeedDeletedCond delete needs less one condition error -var ErrNeedDeletedCond = errors.New("Delete action needs at least one condition") - -func (session *Session) cacheDelete(table *schemas.Table, tableName, sqlStr string, args ...interface{}) error { - if table == nil || - session.tx != nil { - return ErrCacheFailed - } - - for _, filter := range session.engine.dialect.Filters() { - sqlStr = filter.Do(session.ctx, sqlStr) - } - - newsql := session.statement.ConvertIDSQL(sqlStr) - if newsql == "" { - return ErrCacheFailed - } - - cacher := session.engine.cacherMgr.GetCacher(tableName) - pkColumns := table.PKColumns() - ids, err := caches.GetCacheSql(cacher, tableName, newsql, args) - if err != nil { - rows, err := session.queryRows(newsql, args...) - if err != nil { - return err - } - defer rows.Close() - - resultsSlice, err := session.engine.ScanStringMaps(rows) - if err != nil { - return err - } - ids = make([]schemas.PK, 0) - if len(resultsSlice) > 0 { - for _, data := range resultsSlice { - var id int64 - var pk schemas.PK = make([]interface{}, 0) - for _, col := range pkColumns { - if v, ok := data[col.Name]; !ok { - return errors.New("no id") - } else if col.SQLType.IsText() { - pk = append(pk, v) - } else if col.SQLType.IsNumeric() { - id, err = strconv.ParseInt(v, 10, 64) - if err != nil { - return err - } - pk = append(pk, id) - } else { - return errors.New("not supported primary key type") - } - } - ids = append(ids, pk) - } - } - } - - for _, id := range ids { - session.engine.logger.Debugf("[cache] delete cache obj: %v, %v", tableName, id) - sid, err := id.ToString() - if err != nil { - return err - } - cacher.DelBean(tableName, sid) - } - session.engine.logger.Debugf("[cache] clear cache table: %v", tableName) - cacher.ClearIds(tableName) - return nil -} - -// Delete records, bean's non-empty fields are conditions -// At least one condition must be set. -func (session *Session) Delete(beans ...interface{}) (int64, error) { - return session.delete(beans, true) -} - -// Truncate records, bean's non-empty fields are conditions -// In contrast to Delete this method allows deletes without conditions. -func (session *Session) Truncate(beans ...interface{}) (int64, error) { - return session.delete(beans, false) -} - -func (session *Session) delete(beans []interface{}, mustHaveConditions bool) (int64, error) { - if session.isAutoClose { - defer session.Close() - } - - if session.statement.LastError != nil { - return 0, session.statement.LastError - } - - var ( - err error - bean interface{} - ) - if len(beans) > 0 { - bean = beans[0] - if err = session.statement.SetRefBean(bean); err != nil { - return 0, err - } - - executeBeforeClosures(session, bean) - - if processor, ok := interface{}(bean).(BeforeDeleteProcessor); ok { - processor.BeforeDelete() - } - - if err = session.statement.MergeConds(bean); err != nil { - return 0, err - } - } - - pLimitN := session.statement.LimitN - if mustHaveConditions && !session.statement.Conds().IsValid() && (pLimitN == nil || *pLimitN == 0) { - return 0, ErrNeedDeletedCond - } - - tableNameNoQuote := session.statement.TableName() - table := session.statement.RefTable - - realSQLWriter := builder.NewWriter() - deleteSQLWriter := builder.NewWriter() - if err := session.statement.WriteDelete(realSQLWriter, deleteSQLWriter, session.engine.nowTime); err != nil { - return 0, err - } - - if session.statement.GetUnscoped() || table == nil || table.DeletedColumn() == nil { // tag "deleted" is disabled - } else { - deletedColumn := table.DeletedColumn() - _, t, err := session.engine.nowTime(deletedColumn) - if err != nil { - return 0, err - } - - colName := deletedColumn.Name - session.afterClosures = append(session.afterClosures, func(bean interface{}) { - col := table.GetColumn(colName) - setColumnTime(bean, col, t) - }) - } - - argsForCache := make([]interface{}, 0, len(deleteSQLWriter.Args())*2) - copy(argsForCache, deleteSQLWriter.Args()) - argsForCache = append(deleteSQLWriter.Args(), argsForCache...) - - if cacher := session.engine.GetCacher(tableNameNoQuote); cacher != nil && session.statement.UseCache { - _ = session.cacheDelete(table, tableNameNoQuote, deleteSQLWriter.String(), argsForCache...) - } - - session.statement.RefTable = table - res, err := session.exec(realSQLWriter.String(), realSQLWriter.Args()...) - if err != nil { - return 0, err - } - - if bean != nil { - // handle after delete processors - if session.isAutoCommit { - for _, closure := range session.afterClosures { - closure(bean) - } - if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok { - processor.AfterDelete() - } - } else { - lenAfterClosures := len(session.afterClosures) - if lenAfterClosures > 0 && len(beans) > 0 { - if value, has := session.afterDeleteBeans[beans[0]]; has && value != nil { - *value = append(*value, session.afterClosures...) - } else { - afterClosures := make([]func(interface{}), lenAfterClosures) - copy(afterClosures, session.afterClosures) - session.afterDeleteBeans[bean] = &afterClosures - } - } else { - if _, ok := interface{}(bean).(AfterDeleteProcessor); ok { - session.afterDeleteBeans[bean] = nil - } - } - } - } - cleanupProcessorsClosures(&session.afterClosures) - // -- - - return res.RowsAffected() -} diff --git a/session_exist.go b/session_exist.go deleted file mode 100644 index b5e4a655..00000000 --- a/session_exist.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package xorm - -// Exist returns true if the record exist otherwise return false -func (session *Session) Exist(bean ...interface{}) (bool, error) { - if session.isAutoClose { - defer session.Close() - } - - if session.statement.LastError != nil { - return false, session.statement.LastError - } - - sqlStr, args, err := session.statement.GenExistSQL(bean...) - if err != nil { - return false, err - } - - rows, err := session.queryRows(sqlStr, args...) - if err != nil { - return false, err - } - defer rows.Close() - - if rows.Next() { - return true, nil - } - return false, rows.Err() -} diff --git a/session_stats.go b/stats.go similarity index 76% rename from session_stats.go rename to stats.go index be98e467..bbbc6ba6 100644 --- a/session_stats.go +++ b/stats.go @@ -12,7 +12,7 @@ import ( // Count counts the records. bean's non-empty fields // are conditions. -func (session *Session) Count(bean ...interface{}) (int64, error) { +func (session *Session) Count(bean ...any) (int64, error) { if session.isAutoClose { defer session.Close() } @@ -32,7 +32,7 @@ func (session *Session) Count(bean ...interface{}) (int64, error) { } // sum call sum some column. bean's non-empty fields are conditions. -func (session *Session) sum(res interface{}, bean interface{}, columnNames ...string) error { +func (session *Session) sum(res any, bean any, columnNames ...string) error { if session.isAutoClose { defer session.Close() } @@ -59,23 +59,23 @@ func (session *Session) sum(res interface{}, bean interface{}, columnNames ...st } // Sum call sum some column. bean's non-empty fields are conditions. -func (session *Session) Sum(bean interface{}, columnName string) (res float64, err error) { +func (session *Session) Sum(bean any, columnName string) (res float64, err error) { return res, session.sum(&res, bean, columnName) } // SumInt call sum some column. bean's non-empty fields are conditions. -func (session *Session) SumInt(bean interface{}, columnName string) (res int64, err error) { +func (session *Session) SumInt(bean any, columnName string) (res int64, err error) { return res, session.sum(&res, bean, columnName) } // Sums call sum some columns. bean's non-empty fields are conditions. -func (session *Session) Sums(bean interface{}, columnNames ...string) ([]float64, error) { +func (session *Session) Sums(bean any, columnNames ...string) ([]float64, error) { res := make([]float64, len(columnNames)) return res, session.sum(&res, bean, columnNames...) } // SumsInt sum specify columns and return as []int64 instead of []float64 -func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int64, error) { +func (session *Session) SumsInt(bean any, columnNames ...string) ([]int64, error) { res := make([]int64, len(columnNames)) return res, session.sum(&res, bean, columnNames...) } diff --git a/sync.go b/sync.go index adc2d859..20e12971 100644 --- a/sync.go +++ b/sync.go @@ -7,8 +7,8 @@ package xorm import ( "strings" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) type SyncOptions struct { @@ -24,14 +24,14 @@ type SyncResult struct{} // Sync the new struct changes to database, this method will automatically add // table, column, index, unique. but will not delete or change anything. // If you change some field, you should change the database manually. -func (engine *Engine) Sync(beans ...interface{}) error { +func (engine *Engine) Sync(beans ...any) error { session := engine.NewSession() defer session.Close() return session.Sync(beans...) } // SyncWithOptions sync the database schemas according options and table structs -func (engine *Engine) SyncWithOptions(opts SyncOptions, beans ...interface{}) (*SyncResult, error) { +func (engine *Engine) SyncWithOptions(opts SyncOptions, beans ...any) (*SyncResult, error) { session := engine.NewSession() defer session.Close() return session.SyncWithOptions(opts, beans...) @@ -39,18 +39,18 @@ func (engine *Engine) SyncWithOptions(opts SyncOptions, beans ...interface{}) (* // Sync2 synchronize structs to database tables // Depricated -func (engine *Engine) Sync2(beans ...interface{}) error { +func (engine *Engine) Sync2(beans ...any) error { return engine.Sync(beans...) } // Sync2 synchronize structs to database tables // Depricated -func (session *Session) Sync2(beans ...interface{}) error { +func (session *Session) Sync2(beans ...any) error { return session.Sync(beans...) } // Sync synchronize structs to database tables -func (session *Session) Sync(beans ...interface{}) error { +func (session *Session) Sync(beans ...any) error { _, err := session.SyncWithOptions(SyncOptions{ WarnIfDatabaseColumnMissed: false, IgnoreConstrains: false, @@ -59,7 +59,7 @@ func (session *Session) Sync(beans ...interface{}) error { return err } -func (session *Session) SyncWithOptions(opts SyncOptions, beans ...interface{}) (*SyncResult, error) { +func (session *Session) SyncWithOptions(opts SyncOptions, beans ...any) (*SyncResult, error) { engine := session.engine if session.isAutoClose { @@ -67,7 +67,7 @@ func (session *Session) SyncWithOptions(opts SyncOptions, beans ...interface{}) defer session.Close() } - tables, err := engine.dialect.GetTables(session.getQueryer(), session.ctx) + tables, err := engine.dialect.GetTables(session.ctx, session.getQueryer()) if err != nil { return nil, err } diff --git a/tags/parser.go b/tags/parser.go index 53ef0c10..70f255a6 100644 --- a/tags/parser.go +++ b/tags/parser.go @@ -5,20 +5,17 @@ package tags import ( - "encoding/gob" "errors" "fmt" "reflect" "strings" "sync" - "time" "unicode" - "xorm.io/xorm/caches" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" ) // ErrUnsupportedType represents an unsupported type error @@ -44,19 +41,17 @@ type Parser struct { columnMapper names.Mapper tableMapper names.Mapper handlers map[string]Handler - cacherMgr *caches.Manager tableCache sync.Map // map[reflect.Type]*schemas.Table } // NewParser creates a tag parser -func NewParser(identifier string, dialect dialects.Dialect, tableMapper, columnMapper names.Mapper, cacherMgr *caches.Manager) *Parser { +func NewParser(identifier string, dialect dialects.Dialect, tableMapper, columnMapper names.Mapper) *Parser { return &Parser{ identifier: identifier, dialect: dialect, tableMapper: tableMapper, columnMapper: columnMapper, handlers: defaultTagHandlers, - cacherMgr: cacherMgr, } } @@ -103,14 +98,6 @@ func (parser *Parser) ParseWithCache(v reflect.Value) (*schemas.Table, error) { parser.tableCache.Store(t, table) - if parser.cacherMgr.GetDefaultCacher() != nil { - if v.CanAddr() { - gob.Register(v.Addr().Interface()) - } else { - gob.Register(v.Interface()) - } - } - return table, nil } @@ -236,17 +223,6 @@ func (parser *Parser) parseFieldWithTags(table *schemas.Table, fieldIndex int, f col.Name = ctx.tag.name } } - - if ctx.hasCacheTag { - if parser.cacherMgr.GetDefaultCacher() != nil { - parser.cacherMgr.SetCacher(table.Name, parser.cacherMgr.GetDefaultCacher()) - } else { - parser.cacherMgr.SetCacher(table.Name, caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000)) - } - } - if ctx.hasNoCacheTag { - parser.cacherMgr.SetCacher(table.Name, nil) - } } if col.SQLType.Name == "" { diff --git a/tags/parser_test.go b/tags/parser_test.go index 434cfc07..7a8475af 100644 --- a/tags/parser_test.go +++ b/tags/parser_test.go @@ -10,10 +10,9 @@ import ( "testing" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/dialects" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) @@ -46,7 +45,6 @@ func TestParseTableName(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.SnakeMapper{}, - caches.NewManager(), ) table, err := parser.Parse(reflect.ValueOf(new(ParseTableName1))) assert.NoError(t, err) @@ -67,7 +65,6 @@ func TestParseTableComment(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.SnakeMapper{}, - caches.NewManager(), ) table, err := parser.Parse(reflect.ValueOf(new(ParseTableComment))) @@ -97,7 +94,6 @@ func TestUnexportField(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.SnakeMapper{}, - caches.NewManager(), ) type VanilaStruct struct { @@ -130,7 +126,6 @@ func TestParseWithOtherIdentifier(t *testing.T) { dialects.QueryDialect("mysql"), names.SameMapper{}, names.SnakeMapper{}, - caches.NewManager(), ) type StructWithDBTag struct { @@ -154,7 +149,6 @@ func TestParseWithIgnore(t *testing.T) { dialects.QueryDialect("mysql"), names.SameMapper{}, names.SnakeMapper{}, - caches.NewManager(), ) type StructWithIgnoreTag struct { @@ -173,7 +167,6 @@ func TestParseWithAutoincrement(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithAutoIncrement struct { @@ -195,7 +188,6 @@ func TestParseWithAutoincrement2(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithAutoIncrement2 struct { @@ -218,7 +210,6 @@ func TestParseWithNullable(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithNullable struct { @@ -243,7 +234,6 @@ func TestParseWithTimes(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithTimes struct { @@ -276,7 +266,6 @@ func TestParseWithExtends(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithEmbed struct { @@ -307,59 +296,12 @@ func TestParseWithExtends(t *testing.T) { assert.True(t, table.Columns()[3].IsDeleted) } -func TestParseWithCache(t *testing.T) { - parser := NewParser( - "db", - dialects.QueryDialect("mysql"), - names.SnakeMapper{}, - names.GonicMapper{}, - caches.NewManager(), - ) - - type StructWithCache struct { - Name string `db:"cache"` - } - - table, err := parser.Parse(reflect.ValueOf(new(StructWithCache))) - assert.NoError(t, err) - assert.EqualValues(t, "struct_with_cache", table.Name) - assert.EqualValues(t, 1, len(table.Columns())) - assert.EqualValues(t, "name", table.Columns()[0].Name) - assert.True(t, table.Columns()[0].Nullable) - cacher := parser.cacherMgr.GetCacher(table.Name) - assert.NotNil(t, cacher) -} - -func TestParseWithNoCache(t *testing.T) { - parser := NewParser( - "db", - dialects.QueryDialect("mysql"), - names.SnakeMapper{}, - names.GonicMapper{}, - caches.NewManager(), - ) - - type StructWithNoCache struct { - Name string `db:"nocache"` - } - - table, err := parser.Parse(reflect.ValueOf(new(StructWithNoCache))) - assert.NoError(t, err) - assert.EqualValues(t, "struct_with_no_cache", table.Name) - assert.EqualValues(t, 1, len(table.Columns())) - assert.EqualValues(t, "name", table.Columns()[0].Name) - assert.True(t, table.Columns()[0].Nullable) - cacher := parser.cacherMgr.GetCacher(table.Name) - assert.Nil(t, cacher) -} - func TestParseWithEnum(t *testing.T) { parser := NewParser( "db", dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithEnum struct { @@ -385,7 +327,6 @@ func TestParseWithSet(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithSet struct { @@ -411,7 +352,6 @@ func TestParseWithIndex(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithIndex struct { @@ -441,7 +381,6 @@ func TestParseWithVersion(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithVersion struct { @@ -466,7 +405,6 @@ func TestParseWithLocale(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithLocale struct { @@ -490,7 +428,6 @@ func TestParseWithDefault(t *testing.T) { dialects.QueryDialect("mysql"), names.SnakeMapper{}, names.GonicMapper{}, - caches.NewManager(), ) type StructWithDefault struct { @@ -516,7 +453,6 @@ func TestParseWithOnlyToDB(t *testing.T) { "DB": true, }, names.SnakeMapper{}, - caches.NewManager(), ) type StructWithOnlyToDB struct { @@ -542,7 +478,6 @@ func TestParseWithJSON(t *testing.T) { "JSON": true, }, names.SnakeMapper{}, - caches.NewManager(), ) type StructWithJSON struct { @@ -565,7 +500,6 @@ func TestParseWithJSONB(t *testing.T) { "JSONB": true, }, names.SnakeMapper{}, - caches.NewManager(), ) type StructWithJSONB struct { @@ -590,7 +524,6 @@ func TestParseWithSQLType(t *testing.T) { names.GonicMapper{ "UUID": true, }, - caches.NewManager(), ) type StructWithSQLType struct { diff --git a/tags/tag.go b/tags/tag.go index 55f0b7c7..da75706f 100644 --- a/tags/tag.go +++ b/tags/tag.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) type tag struct { @@ -90,8 +90,6 @@ type Context struct { isUnique bool indexNames map[string]int parser *Parser - hasCacheTag bool - hasNoCacheTag bool ignoreNext bool isUnsigned bool } @@ -118,8 +116,6 @@ var defaultTagHandlers = map[string]Handler{ "NOTNULL": NotNullTagHandler, "INDEX": IndexTagHandler, "UNIQUE": UniqueTagHandler, - "CACHE": CacheTagHandler, - "NOCACHE": NoCacheTagHandler, "COMMENT": CommentTagHandler, "EXTENDS": ExtendsTagHandler, "UNSIGNED": UnsignedTagHandler, @@ -391,19 +387,3 @@ func ExtendsTagHandler(ctx *Context) error { } return ErrIgnoreField } - -// CacheTagHandler describes cache tag handler -func CacheTagHandler(ctx *Context) error { - if !ctx.hasCacheTag { - ctx.hasCacheTag = true - } - return nil -} - -// NoCacheTagHandler describes nocache tag handler -func NoCacheTagHandler(ctx *Context) error { - if !ctx.hasNoCacheTag { - ctx.hasNoCacheTag = true - } - return nil -} diff --git a/tests/cache_test.go b/tests/cache_test.go deleted file mode 100644 index c3f84c77..00000000 --- a/tests/cache_test.go +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright 2017 The Xorm Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package tests - -import ( - "testing" - "time" - - "xorm.io/xorm/caches" - - "github.com/stretchr/testify/assert" -) - -func TestCacheFind(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - type MailBox struct { - Id int64 `xorm:"pk"` - Username string - Password string - } - - oldCacher := testEngine.GetDefaultCacher() - cacher := caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000) - testEngine.SetDefaultCacher(cacher) - - assert.NoError(t, testEngine.Sync(new(MailBox))) - - inserts := []*MailBox{ - { - Id: 0, - Username: "user1", - Password: "pass1", - }, - { - Id: 1, - Username: "user2", - Password: "pass2", - }, - } - _, err := testEngine.Insert(inserts[0], inserts[1]) - assert.NoError(t, err) - - var boxes []MailBox - assert.NoError(t, testEngine.Find(&boxes)) - assert.EqualValues(t, 2, len(boxes)) - for i, box := range boxes { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - boxes = make([]MailBox, 0, 2) - assert.NoError(t, testEngine.Find(&boxes)) - assert.EqualValues(t, 2, len(boxes)) - for i, box := range boxes { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - boxes = make([]MailBox, 0, 2) - assert.NoError(t, testEngine.Alias("a").Where("`a`.`id`> -1"). - Asc("`a`.`id`").Find(&boxes)) - assert.EqualValues(t, 2, len(boxes)) - for i, box := range boxes { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - type MailBox4 struct { - Id int64 - Username string - Password string - } - - boxes2 := make([]MailBox4, 0, 2) - assert.NoError(t, testEngine.Table("mail_box").Where("`mail_box`.`id` > -1"). - Asc("mail_box.id").Find(&boxes2)) - assert.EqualValues(t, 2, len(boxes2)) - for i, box := range boxes2 { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - testEngine.SetDefaultCacher(oldCacher) -} - -func TestCacheFind2(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - type MailBox2 struct { - Id uint64 `xorm:"pk"` - Username string - Password string - } - - oldCacher := testEngine.GetDefaultCacher() - cacher := caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000) - testEngine.SetDefaultCacher(cacher) - - assert.NoError(t, testEngine.Sync(new(MailBox2))) - - inserts := []*MailBox2{ - { - Id: 0, - Username: "user1", - Password: "pass1", - }, - { - Id: 1, - Username: "user2", - Password: "pass2", - }, - } - _, err := testEngine.Insert(inserts[0], inserts[1]) - assert.NoError(t, err) - - var boxes []MailBox2 - assert.NoError(t, testEngine.Find(&boxes)) - assert.EqualValues(t, 2, len(boxes)) - for i, box := range boxes { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - boxes = make([]MailBox2, 0, 2) - assert.NoError(t, testEngine.Find(&boxes)) - assert.EqualValues(t, 2, len(boxes)) - for i, box := range boxes { - assert.Equal(t, inserts[i].Id, box.Id) - assert.Equal(t, inserts[i].Username, box.Username) - assert.Equal(t, inserts[i].Password, box.Password) - } - - testEngine.SetDefaultCacher(oldCacher) -} - -func TestCacheGet(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - type MailBox3 struct { - Id uint64 - Username string - Password string - } - - oldCacher := testEngine.GetDefaultCacher() - cacher := caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000) - testEngine.SetDefaultCacher(cacher) - - assert.NoError(t, testEngine.Sync(new(MailBox3))) - - inserts := []*MailBox3{ - { - Username: "user1", - Password: "pass1", - }, - } - _, err := testEngine.Insert(inserts[0]) - assert.NoError(t, err) - - var box1 MailBox3 - has, err := testEngine.Where("`id` = ?", inserts[0].Id).Get(&box1) - assert.NoError(t, err) - assert.True(t, has) - assert.EqualValues(t, "user1", box1.Username) - assert.EqualValues(t, "pass1", box1.Password) - - var box2 MailBox3 - has, err = testEngine.Where("`id` = ?", inserts[0].Id).Get(&box2) - assert.NoError(t, err) - assert.True(t, has) - assert.EqualValues(t, "user1", box2.Username) - assert.EqualValues(t, "pass1", box2.Password) - - testEngine.SetDefaultCacher(oldCacher) -} diff --git a/tests/engine_dm_test.go b/tests/engine_dm_test.go index 5b25af29..9d4a0e66 100644 --- a/tests/engine_dm_test.go +++ b/tests/engine_dm_test.go @@ -7,7 +7,7 @@ package tests -import "xorm.io/xorm/schemas" +import "xorm.io/xorm/v2/schemas" func init() { dbtypes = append(dbtypes, schemas.DAMENG) diff --git a/tests/engine_group_test.go b/tests/engine_group_test.go index 629e0aa4..fab25c67 100644 --- a/tests/engine_group_test.go +++ b/tests/engine_group_test.go @@ -7,9 +7,9 @@ package tests import ( "testing" - "xorm.io/xorm" - "xorm.io/xorm/log" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) diff --git a/tests/engine_test.go b/tests/engine_test.go index 79ca42f5..b482df73 100644 --- a/tests/engine_test.go +++ b/tests/engine_test.go @@ -11,8 +11,8 @@ import ( "testing" "time" - "xorm.io/xorm" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/schemas" _ "gitee.com/travelliu/dm" _ "github.com/denisenkom/go-mssqldb" @@ -21,7 +21,6 @@ import ( _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" "github.com/stretchr/testify/assert" - _ "github.com/ziutek/mymysql/godrv" _ "modernc.org/sqlite" ) @@ -58,7 +57,7 @@ func TestAutoTransaction(t *testing.T) { engine := testEngine.(*xorm.Engine) // will success - _, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err := engine.Transaction(func(session *xorm.Session) (any, error) { _, err := session.Insert(TestTx{Msg: "hi"}) assert.NoError(t, err) @@ -71,7 +70,7 @@ func TestAutoTransaction(t *testing.T) { assert.EqualValues(t, true, has) // will rollback - _, err = engine.Transaction(func(session *xorm.Session) (interface{}, error) { + _, err = engine.Transaction(func(session *xorm.Session) (any, error) { _, err := session.Insert(TestTx{Msg: "hello"}) assert.NoError(t, err) @@ -84,7 +83,7 @@ func TestAutoTransaction(t *testing.T) { assert.EqualValues(t, false, has) } -func assertSync(t *testing.T, beans ...interface{}) { +func assertSync(t *testing.T, beans ...any) { for _, bean := range beans { t.Run(testEngine.TableName(bean, true), func(t *testing.T) { assert.NoError(t, testEngine.DropTables(bean)) diff --git a/tests/processors_test.go b/tests/processors_test.go index af2866e8..9fc46f1b 100644 --- a/tests/processors_test.go +++ b/tests/processors_test.go @@ -9,7 +9,7 @@ import ( "fmt" "testing" - "xorm.io/xorm" + "xorm.io/xorm/v2" "github.com/stretchr/testify/assert" ) @@ -32,7 +32,7 @@ func TestBefore_Get(t *testing.T) { assert.EqualValues(t, 1, cnt) var be BeforeTable - has, err := testEngine.Before(func(bean interface{}) { + has, err := testEngine.Before(func(bean any) { bean.(*BeforeTable).Val = "val" }).Get(&be) assert.NoError(t, err) @@ -60,7 +60,7 @@ func TestBefore_Find(t *testing.T) { assert.EqualValues(t, 2, cnt) var be []BeforeTable2 - err = testEngine.Before(func(bean interface{}) { + err = testEngine.Before(func(bean any) { bean.(*BeforeTable2).Val = "val" }).Find(&be) assert.NoError(t, err) @@ -133,7 +133,7 @@ func TestProcessors(t *testing.T) { err = testEngine.CreateTables(&ProcessorsStruct{}) assert.NoError(t, err) - b4InsertFunc := func(bean interface{}) { + b4InsertFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4InsertViaExt = 1 } else { @@ -141,7 +141,7 @@ func TestProcessors(t *testing.T) { } } - afterInsertFunc := func(bean interface{}) { + afterInsertFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterInsertedViaExt = 1 } else { @@ -234,7 +234,7 @@ func TestProcessors(t *testing.T) { // -- // test update processors - b4UpdateFunc := func(bean interface{}) { + b4UpdateFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4UpdateViaExt = 1 } else { @@ -242,7 +242,7 @@ func TestProcessors(t *testing.T) { } } - afterUpdateFunc := func(bean interface{}) { + afterUpdateFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterUpdatedViaExt = 1 } else { @@ -274,7 +274,7 @@ func TestProcessors(t *testing.T) { // -- // test delete processors - b4DeleteFunc := func(bean interface{}) { + b4DeleteFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4DeleteViaExt = 1 } else { @@ -282,7 +282,7 @@ func TestProcessors(t *testing.T) { } } - afterDeleteFunc := func(bean interface{}) { + afterDeleteFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterDeletedViaExt = 1 } else { @@ -374,7 +374,7 @@ func TestProcessorsTx(t *testing.T) { assert.NoError(t, err) p := &ProcessorsStruct{} - b4InsertFunc := func(bean interface{}) { + b4InsertFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4InsertViaExt = 1 } else { @@ -382,7 +382,7 @@ func TestProcessorsTx(t *testing.T) { } } - afterInsertFunc := func(bean interface{}) { + afterInsertFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterInsertedViaExt = 1 } else { @@ -497,7 +497,7 @@ func TestProcessorsTx(t *testing.T) { err = session.Begin() assert.NoError(t, err) - b4UpdateFunc := func(bean interface{}) { + b4UpdateFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4UpdateViaExt = 1 } else { @@ -505,7 +505,7 @@ func TestProcessorsTx(t *testing.T) { } } - afterUpdateFunc := func(bean interface{}) { + afterUpdateFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterUpdatedViaExt = 1 } else { @@ -671,7 +671,7 @@ func TestProcessorsTx(t *testing.T) { err = session.Begin() assert.NoError(t, err) - b4DeleteFunc := func(bean interface{}) { + b4DeleteFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.B4DeleteViaExt = 1 } else { @@ -679,7 +679,7 @@ func TestProcessorsTx(t *testing.T) { } } - afterDeleteFunc := func(bean interface{}) { + afterDeleteFunc := func(bean any) { if v, ok := (bean).(*ProcessorsStruct); ok { v.AfterDeletedViaExt = 1 } else { @@ -832,6 +832,9 @@ type AfterLoadStructB struct { Err error `xorm:"-"` } +// ErrNotExist record does not exist error +var ErrNotExist = errors.New("Record does not exist") + func (s *AfterLoadStructB) AfterLoad(session *xorm.Session) { has, err := session.ID(s.AId).NoAutoCondition().Get(&s.A) if err != nil { @@ -839,7 +842,7 @@ func (s *AfterLoadStructB) AfterLoad(session *xorm.Session) { return } if !has { - s.Err = xorm.ErrNotExist + s.Err = ErrNotExist } } diff --git a/tests/schema_test.go b/tests/schema_test.go index db9f9e8f..67c68893 100644 --- a/tests/schema_test.go +++ b/tests/schema_test.go @@ -11,9 +11,10 @@ import ( "testing" "time" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/schemas" + "github.com/stretchr/testify/assert" - "xorm.io/xorm" - "xorm.io/xorm/schemas" ) func TestStoreEngine(t *testing.T) { @@ -716,10 +717,9 @@ func TestSyncWithOptions(t *testing.T) { tableInfoFromStruct, _ := testEngine.TableInfo(&SyncWithOpts1{}) assert.ElementsMatch(t, getKeysFromMap(tableInfoFromStruct.Indexes), getKeysFromMap(getIndicesOfBeanFromDB(t, &SyncWithOpts1{}))) - } -func getIndicesOfBeanFromDB(t *testing.T, bean interface{}) map[string]*schemas.Index { +func getIndicesOfBeanFromDB(t *testing.T, bean any) map[string]*schemas.Index { dbm, err := testEngine.DBMetas() assert.NoError(t, err) diff --git a/tests/session_cols_test.go b/tests/session_cols_test.go index 4a6ef39f..1846168f 100644 --- a/tests/session_cols_test.go +++ b/tests/session_cols_test.go @@ -7,9 +7,10 @@ package tests import ( "testing" - "github.com/stretchr/testify/assert" "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" + + "github.com/stretchr/testify/assert" ) func TestSetExpr(t *testing.T) { diff --git a/tests/session_cond_test.go b/tests/session_cond_test.go index cbcd0cb5..ce7cd03e 100644 --- a/tests/session_cond_test.go +++ b/tests/session_cond_test.go @@ -155,7 +155,7 @@ func TestIn(t *testing.T) { } users = make([]Userinfo, 0) - var idsInterface []interface{} + var idsInterface []any for _, id := range ids { idsInterface = append(idsInterface, id) } diff --git a/tests/session_delete_test.go b/tests/session_delete_test.go index 44d4ad7d..2e546873 100644 --- a/tests/session_delete_test.go +++ b/tests/session_delete_test.go @@ -9,8 +9,7 @@ import ( "testing" "time" - "xorm.io/xorm/caches" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) @@ -217,38 +216,6 @@ func TestDeleted(t *testing.T) { assert.EqualValues(t, 2, len(records3)) } -func TestCacheDelete(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - oldCacher := testEngine.GetDefaultCacher() - cacher := caches.NewLRUCacher(caches.NewMemoryStore(), 1000) - testEngine.SetDefaultCacher(cacher) - - type CacheDeleteStruct struct { - Id int64 - } - - err := testEngine.CreateTables(&CacheDeleteStruct{}) - assert.NoError(t, err) - - _, err = testEngine.Insert(&CacheDeleteStruct{}) - assert.NoError(t, err) - - aff, err := testEngine.Delete(&CacheDeleteStruct{ - Id: 1, - }) - assert.NoError(t, err) - assert.EqualValues(t, aff, 1) - - aff, err = testEngine.Unscoped().Delete(&CacheDeleteStruct{ - Id: 1, - }) - assert.NoError(t, err) - assert.EqualValues(t, aff, 0) - - testEngine.SetDefaultCacher(oldCacher) -} - func TestUnscopeDelete(t *testing.T) { assert.NoError(t, PrepareEngine()) diff --git a/tests/session_find_test.go b/tests/session_find_test.go index d991e6ba..2b65eb85 100644 --- a/tests/session_find_test.go +++ b/tests/session_find_test.go @@ -9,10 +9,10 @@ import ( "time" "xorm.io/builder" - "xorm.io/xorm" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) @@ -146,7 +146,7 @@ func TestFind3(t *testing.T) { err = testEngine.Cols("`team`.`id`"). Where("`team_user`.`org_id`=?", 1). And("`team_user`.`uid`=?", 2). - Join("INNER", []interface{}{teamUser}, "`team_user`.`team_id`=`team`.`id`"). + Join("INNER", []any{teamUser}, "`team_user`.`team_id`=`team`.`id`"). Find(&teams) assert.NoError(t, err) @@ -162,7 +162,7 @@ func TestFind3(t *testing.T) { err = testEngine.Cols("`team`.`id`"). Where("`tu`.`org_id`=?", 1). And("`tu`.`uid`=?", 2). - Join("INNER", []interface{}{"team_user", "tu"}, "`tu`.`team_id`=`team`.`id`"). + Join("INNER", []any{"team_user", "tu"}, "`tu`.`team_id`=`team`.`id`"). Find(&teams) assert.NoError(t, err) @@ -170,7 +170,7 @@ func TestFind3(t *testing.T) { err = testEngine.Cols("`team`.`id`"). Where("`tu`.`org_id`=?", 1). And("`tu`.`uid`=?", 2). - Join("INNER", []interface{}{teamUser, "tu"}, "`tu`.`team_id`=`team`.`id`"). + Join("INNER", []any{teamUser, "tu"}, "`tu`.`team_id`=`team`.`id`"). Find(&teams) assert.NoError(t, err) } @@ -367,7 +367,7 @@ func TestFindInterface(t *testing.T) { userinfo := testEngine.GetTableMapper().Obj2Table("Userinfo") username := testEngine.GetColumnMapper().Obj2Table("Username") - var idsInterface []interface{} + var idsInterface []any err := testEngine.Table(userinfo).Cols(username).Desc("id").Find(&idsInterface) assert.NoError(t, err) } diff --git a/tests/session_get_test.go b/tests/session_get_test.go index 2ff2f67d..81ea8298 100644 --- a/tests/session_get_test.go +++ b/tests/session_get_test.go @@ -12,11 +12,11 @@ import ( "testing" "time" - "xorm.io/xorm" - "xorm.io/xorm/contexts" - "xorm.io/xorm/convert" - "xorm.io/xorm/dialects" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/contexts" + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/schemas" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" @@ -185,9 +185,8 @@ func TestGetVar(t *testing.T) { assert.Equal(t, "28", valuesString["age"]) assert.Equal(t, "1.5", valuesString["money"]) - // for mymysql driver, interface{} will be []byte, so ignore it currently - if testEngine.DriverName() != "mymysql" { - valuesInter := make(map[string]interface{}) + { + valuesInter := make(map[string]any) has, err = testEngine.Table("get_var").Where("`id` = ?", 1).Select("*").Get(&valuesInter) assert.NoError(t, err) assert.Equal(t, true, has) @@ -207,7 +206,7 @@ func TestGetVar(t *testing.T) { assert.Equal(t, "28", valuesSliceString[2]) assert.Equal(t, "1.5", valuesSliceString[3]) - valuesSliceInter := make([]interface{}, 5) + valuesSliceInter := make([]any, 5) has, err = testEngine.Table("get_var").Get(&valuesSliceInter) assert.NoError(t, err) assert.Equal(t, true, has) @@ -510,7 +509,7 @@ func TestContextGet(t *testing.T) { context := contexts.NewMemoryContextCache() var c2 ContextGetStruct - has, err := sess.ID(1).NoCache().ContextCache(context).Get(&c2) + has, err := sess.ID(1).ContextCache(context).Get(&c2) assert.NoError(t, err) assert.True(t, has) assert.EqualValues(t, 1, c2.Id) @@ -520,7 +519,7 @@ func TestContextGet(t *testing.T) { assert.True(t, len(args) > 0) var c3 ContextGetStruct - has, err = sess.ID(1).NoCache().ContextCache(context).Get(&c3) + has, err = sess.ID(1).ContextCache(context).Get(&c3) assert.NoError(t, err) assert.True(t, has) assert.EqualValues(t, 1, c3.Id) @@ -545,14 +544,14 @@ func TestContextGet2(t *testing.T) { context := contexts.NewMemoryContextCache() var c2 ContextGetStruct2 - has, err := testEngine.ID(1).NoCache().ContextCache(context).Get(&c2) + has, err := testEngine.ID(1).ContextCache(context).Get(&c2) assert.NoError(t, err) assert.True(t, has) assert.EqualValues(t, 1, c2.Id) assert.EqualValues(t, "1", c2.Name) var c3 ContextGetStruct2 - has, err = testEngine.ID(1).NoCache().ContextCache(context).Get(&c3) + has, err = testEngine.ID(1).ContextCache(context).Get(&c3) assert.NoError(t, err) assert.True(t, has) assert.EqualValues(t, 1, c3.Id) @@ -728,7 +727,7 @@ func TestGetViaMapCond(t *testing.T) { r GetViaMapCond platformStr = colMapper.Obj2Table("Platform") indexStr = colMapper.Obj2Table("Index") - query = map[string]interface{}{ + query = map[string]any{ platformStr: 1, indexStr: 1, } diff --git a/tests/session_insert_test.go b/tests/session_insert_test.go index cf8a3ce5..7ee255bb 100644 --- a/tests/session_insert_test.go +++ b/tests/session_insert_test.go @@ -10,8 +10,8 @@ import ( "testing" "time" - "xorm.io/xorm" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) @@ -47,7 +47,7 @@ func TestInsertMulti(t *testing.T) { assert.EqualValues(t, 3, num) } -func insertMultiDatas(step int, datas interface{}) (num int64, err error) { +func insertMultiDatas(step int, datas any) (num int64, err error) { sliceValue := reflect.Indirect(reflect.ValueOf(datas)) var iLen int64 if sliceValue.Kind() != reflect.Slice { @@ -62,7 +62,7 @@ func insertMultiDatas(step int, datas interface{}) (num int64, err error) { defer session.Close() if err = callbackLooper(datas, step, - func(innerDatas interface{}) error { + func(innerDatas any) error { n, e := session.InsertMulti(innerDatas) if e != nil { return e @@ -77,7 +77,7 @@ func insertMultiDatas(step int, datas interface{}) (num int64, err error) { return } -func callbackLooper(datas interface{}, step int, actionFunc func(interface{}) error) (err error) { +func callbackLooper(datas any, step int, actionFunc func(any) error) (err error) { sliceValue := reflect.Indirect(reflect.ValueOf(datas)) if sliceValue.Kind() != reflect.Slice { return fmt.Errorf("not slice") @@ -94,7 +94,7 @@ func callbackLooper(datas interface{}, step int, actionFunc func(interface{}) er } else { tempLen = sliceValue.Len() } - var tempInterface []interface{} + var tempInterface []any for j := i; j < tempLen; j++ { tempInterface = append(tempInterface, sliceValue.Index(j).Interface()) } @@ -482,7 +482,7 @@ func TestInsertMulti2Interface(t *testing.T) { assertSync(t, new(Userinfo)) - users := []interface{}{ + users := []any{ Userinfo{Username: "xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()}, Userinfo{Username: "xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()}, Userinfo{Username: "xlw11", Departname: "dev", Alias: "lunny2", Created: time.Now()}, @@ -496,7 +496,7 @@ func TestInsertMulti2Interface(t *testing.T) { } assert.EqualValues(t, len(users), cnt) - users2 := []interface{}{ + users2 := []any{ &Userinfo{Username: "1xlw", Departname: "dev", Alias: "lunny2", Created: time.Now()}, &Userinfo{Username: "1xlw2", Departname: "dev", Alias: "lunny3", Created: time.Now()}, &Userinfo{Username: "1xlw11", Departname: "dev", Alias: "lunny2", Created: time.Now()}, @@ -683,7 +683,7 @@ func TestInsertMap(t *testing.T) { assert.NoError(t, PrepareEngine()) assertSync(t, new(InsertMap)) - cnt, err := testEngine.Table(new(InsertMap)).Insert(map[string]interface{}{ + cnt, err := testEngine.Table(new(InsertMap)).Insert(map[string]any{ "width": 20, "height": 10, "name": "lunny", @@ -699,7 +699,7 @@ func TestInsertMap(t *testing.T) { assert.EqualValues(t, 10, im.Height) assert.EqualValues(t, "lunny", im.Name) - cnt, err = testEngine.Table("insert_map").Insert(map[string]interface{}{ + cnt, err = testEngine.Table("insert_map").Insert(map[string]any{ "width": 30, "height": 10, "name": "lunny", @@ -718,7 +718,7 @@ func TestInsertMap(t *testing.T) { assert.EqualValues(t, 10, ims[1].Height) assert.EqualValues(t, "lunny", ims[1].Name) - cnt, err = testEngine.Table("insert_map").Insert([]map[string]interface{}{ + cnt, err = testEngine.Table("insert_map").Insert([]map[string]any{ { "width": 40, "height": 10, @@ -797,7 +797,7 @@ func TestInsertWhere(t *testing.T) { inserted, err = testEngine.Table(new(InsertWhere)).Where("`repo_id`=?", 1). SetExpr("`index`", "coalesce(MAX(`index`),0)+1"). - Insert(map[string]interface{}{ + Insert(map[string]any{ "repo_id": 1, "width": 20, "height": 40, @@ -834,7 +834,7 @@ func TestInsertWhere(t *testing.T) { inserted, err = testEngine.Table(new(InsertWhere)).Where("`repo_id`=?", 1). SetExpr("`index`", "coalesce(MAX(`index`),0)+1"). - Insert(map[string]interface{}{ + Insert(map[string]any{ "repo_id": 1, "name": "10';delete * from insert_where; --", }) @@ -850,7 +850,7 @@ func TestInsertWhere(t *testing.T) { inserted, err = testEngine.Table(new(InsertWhere)).Where("`repo_id`=?", 1). SetExpr("`index`", "coalesce(MAX(`index`),0)+1"). - Insert(map[string]interface{}{ + Insert(map[string]any{ "repo_id": 1, "name": "10\\';delete * from insert_where; --", }) @@ -910,7 +910,7 @@ func TestInsertExpr2(t *testing.T) { SetExpr("is_draft", true). SetExpr("num_commits", 0). SetExpr("sha1", ""). - Insert(map[string]interface{}{ + Insert(map[string]any{ "repo_id": 1, "is_tag": true, }) @@ -947,7 +947,7 @@ func TestMultipleInsertTableName(t *testing.T) { err := trans.Begin() assert.NoError(t, err) - rtArr := []interface{}{ + rtArr := []any{ []*NightlyRate{ {ID: 1}, {ID: 2}, @@ -978,7 +978,7 @@ func TestInsertMultiWithOmit(t *testing.T) { assert.NoError(t, testEngine.Sync(new(TestMultiOmit))) - l := []interface{}{ + l := []any{ TestMultiOmit{Id: 1, Name: "1", Omitted: "1"}, TestMultiOmit{Id: 2, Name: "1", Omitted: "2"}, TestMultiOmit{Id: 3, Name: "1", Omitted: "3"}, @@ -1142,7 +1142,7 @@ func TestInsertMultipleMap(t *testing.T) { assert.NoError(t, PrepareEngine()) assertSync(t, new(InsertMultipleMap)) - cnt, err := testEngine.Table(new(InsertMultipleMap)).Insert([]map[string]interface{}{ + cnt, err := testEngine.Table(new(InsertMultipleMap)).Insert([]map[string]any{ { "width": 20, "height": 10, diff --git a/tests/session_iterate_test.go b/tests/session_iterate_test.go index f2e36899..4d839b46 100644 --- a/tests/session_iterate_test.go +++ b/tests/session_iterate_test.go @@ -33,7 +33,7 @@ func TestIterate(t *testing.T) { assert.EqualValues(t, 1, cnt) cnt = 0 - err = testEngine.Iterate(new(UserIterate), func(i int, bean interface{}) error { + err = testEngine.Iterate(new(UserIterate), func(i int, bean any) error { user := bean.(*UserIterate) if cnt == 0 { assert.EqualValues(t, 1, user.Id) @@ -69,7 +69,7 @@ func TestBufferIterate(t *testing.T) { } cnt := 0 - err := testEngine.BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean interface{}) error { + err := testEngine.BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean any) error { user := bean.(*UserBufferIterate) assert.EqualValues(t, cnt+1, user.Id) assert.EqualValues(t, true, user.IsMan) @@ -80,7 +80,7 @@ func TestBufferIterate(t *testing.T) { assert.EqualValues(t, size, cnt) cnt = 0 - err = testEngine.Limit(20).BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean interface{}) error { + err = testEngine.Limit(20).BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean any) error { user := bean.(*UserBufferIterate) assert.EqualValues(t, cnt+1, user.Id) assert.EqualValues(t, true, user.IsMan) @@ -91,7 +91,7 @@ func TestBufferIterate(t *testing.T) { assert.EqualValues(t, size, cnt) cnt = 0 - err = testEngine.Limit(7).BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean interface{}) error { + err = testEngine.Limit(7).BufferSize(9).Iterate(new(UserBufferIterate), func(i int, bean any) error { user := bean.(*UserBufferIterate) assert.EqualValues(t, cnt+1, user.Id) assert.EqualValues(t, true, user.IsMan) @@ -102,7 +102,7 @@ func TestBufferIterate(t *testing.T) { assert.EqualValues(t, 7, cnt) cnt = 0 - err = testEngine.Where("`id` <= 10").BufferSize(2).Iterate(new(UserBufferIterate), func(i int, bean interface{}) error { + err = testEngine.Where("`id` <= 10").BufferSize(2).Iterate(new(UserBufferIterate), func(i int, bean any) error { user := bean.(*UserBufferIterate) assert.EqualValues(t, cnt+1, user.Id) assert.EqualValues(t, true, user.IsMan) diff --git a/tests/session_pk_test.go b/tests/session_pk_test.go index baf84547..95f1394e 100644 --- a/tests/session_pk_test.go +++ b/tests/session_pk_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/stretchr/testify/assert" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" ) type IntId struct { @@ -430,7 +430,7 @@ func TestCompositeKey(t *testing.T) { assert.True(t, has) var compositeKeyVal2 CompositeKey - // test passing PK ptr, this test seem failed withCache + // test passing PK ptr has, err = testEngine.ID(&schemas.PK{11, 22}).Get(&compositeKeyVal2) assert.NoError(t, err) assert.True(t, has) @@ -491,7 +491,7 @@ func TestCompositeKey2(t *testing.T) { assert.NoError(t, err) assert.True(t, has) - // test passing PK ptr, this test seem failed withCache + // test passing PK ptr has, err = testEngine.ID(&schemas.PK{"11", 22}).Get(&user) assert.NoError(t, err) assert.True(t, has) @@ -539,7 +539,7 @@ func TestCompositeKey3(t *testing.T) { assert.NoError(t, err) assert.True(t, has) - // test passing PK ptr, this test seem failed withCache + // test passing PK ptr has, err = testEngine.ID(&schemas.PK{"11", 22}).Get(&user) assert.NoError(t, err) assert.True(t, has) diff --git a/tests/session_query_test.go b/tests/session_query_test.go index 726b19e2..063cd503 100644 --- a/tests/session_query_test.go +++ b/tests/session_query_test.go @@ -12,7 +12,7 @@ import ( "xorm.io/builder" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) @@ -72,7 +72,7 @@ func TestQueryString2(t *testing.T) { assert.True(t, "0" == records[0]["msg"] || "false" == records[0]["msg"]) } -func toBool(i interface{}) bool { +func toBool(i any) bool { switch t := i.(type) { case int32: return t > 0 @@ -422,7 +422,7 @@ func TestQueryBLOBInMySQL(t *testing.T) { } { - arr := make([][]interface{}, 0) + arr := make([][]any, 0) err = testEngine.Table(testEngine.Quote(testEngine.TableName("avatar", true))).Cols("avatar").Find(&arr) assert.NoError(t, err) for i, record := range arr { @@ -433,7 +433,7 @@ func TestQueryBLOBInMySQL(t *testing.T) { } { - arr := make([]map[string]interface{}, 0) + arr := make([]map[string]any, 0) err = testEngine.Table(testEngine.Quote(testEngine.TableName("avatar", true))).Cols("avatar").Find(&arr) assert.NoError(t, err) for i, record := range arr { @@ -493,4 +493,4 @@ func TestRowsReset(t *testing.T) { assert.EqualValues(t, "4", rrs[0].Name) assert.EqualValues(t, "5", rrs[1].Name) assert.EqualValues(t, "6", rrs[2].Name) -} \ No newline at end of file +} diff --git a/tests/session_raw_test.go b/tests/session_raw_test.go index 569d7bed..18ea6d59 100644 --- a/tests/session_raw_test.go +++ b/tests/session_raw_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "xorm.io/xorm/convert" + "xorm.io/xorm/v2/internal/convert" "github.com/stretchr/testify/assert" ) diff --git a/tests/session_tx_test.go b/tests/session_tx_test.go index c9db40ba..b00a8ecb 100644 --- a/tests/session_tx_test.go +++ b/tests/session_tx_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/stretchr/testify/assert" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/names" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/names" ) func TestTransaction(t *testing.T) { @@ -201,7 +201,7 @@ func TestInsertMulti2InterfaceTransaction(t *testing.T) { err := session.Begin() assert.NoError(t, err) - users := []interface{}{ + users := []any{ &Multi2InterfaceTransaction{Name: "a", Alias: "A"}, &Multi2InterfaceTransaction{Name: "b", Alias: "B"}, &Multi2InterfaceTransaction{Name: "c", Alias: "C"}, diff --git a/tests/session_update_test.go b/tests/session_update_test.go index c13468d9..3528e6d0 100644 --- a/tests/session_update_test.go +++ b/tests/session_update_test.go @@ -10,12 +10,13 @@ import ( "testing" "time" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/internal/statements" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" + "github.com/stretchr/testify/assert" - "xorm.io/xorm" - "xorm.io/xorm/internal/statements" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" ) func TestUpdateMap(t *testing.T) { @@ -35,14 +36,14 @@ func TestUpdateMap(t *testing.T) { _, err := testEngine.Insert(&tb) assert.NoError(t, err) - cnt, err := testEngine.Table("update_table").Where("`id` = ?", tb.Id).Update(map[string]interface{}{ + cnt, err := testEngine.Table("update_table").Where("`id` = ?", tb.Id).Update(map[string]any{ "name": "test2", "age": 36, }) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) - cnt, err = testEngine.Table("update_table").ID(tb.Id).Update(map[string]interface{}{ + cnt, err = testEngine.Table("update_table").ID(tb.Id).Update(map[string]any{ "name": "test2", "age": 36, }) @@ -50,7 +51,7 @@ func TestUpdateMap(t *testing.T) { assert.True(t, statements.IsIDConditionWithNoTableErr(err)) assert.EqualValues(t, 0, cnt) - cnt, err = testEngine.Table("update_table").Update(map[string]interface{}{ + cnt, err = testEngine.Table("update_table").Update(map[string]any{ "name": "test2", "age": 36, }, &UpdateTable{ @@ -269,7 +270,7 @@ func TestWithIn(t *testing.T) { assert.EqualValues(t, 3, cnt) } -type Condi map[string]interface{} +type Condi map[string]any type UpdateAllCols struct { Id int64 @@ -304,7 +305,7 @@ func TestUpdateMap2(t *testing.T) { assert.NoError(t, PrepareEngine()) assertSync(t, new(UpdateMustCols)) - _, err := testEngine.Table("update_must_cols").Where("`id` =?", 1).Update(map[string]interface{}{ + _, err := testEngine.Table("update_must_cols").Where("`id` =?", 1).Update(map[string]any{ "bool": true, }) assert.NoError(t, err) @@ -809,17 +810,17 @@ func TestNewUpdate(t *testing.T) { assert.NoError(t, PrepareEngine()) type TbUserInfo struct { - Id int64 `xorm:"pk autoincr unique BIGINT" json:"id"` - Phone string `xorm:"not null unique VARCHAR(20)" json:"phone"` - UserName string `xorm:"VARCHAR(20)" json:"user_name"` - Gender int `xorm:"default 0 INTEGER" json:"gender"` - Pw string `xorm:"VARCHAR(100)" json:"pw"` - Token string `xorm:"TEXT" json:"token"` - Avatar string `xorm:"TEXT" json:"avatar"` - Extras interface{} `xorm:"JSON" json:"extras"` - Created time.Time `xorm:"DATETIME created"` - Updated time.Time `xorm:"DATETIME updated"` - Deleted time.Time `xorm:"DATETIME deleted"` + Id int64 `xorm:"pk autoincr unique BIGINT" json:"id"` + Phone string `xorm:"not null unique VARCHAR(20)" json:"phone"` + UserName string `xorm:"VARCHAR(20)" json:"user_name"` + Gender int `xorm:"default 0 INTEGER" json:"gender"` + Pw string `xorm:"VARCHAR(100)" json:"pw"` + Token string `xorm:"TEXT" json:"token"` + Avatar string `xorm:"TEXT" json:"avatar"` + Extras any `xorm:"JSON" json:"extras"` + Created time.Time `xorm:"DATETIME created"` + Updated time.Time `xorm:"DATETIME updated"` + Deleted time.Time `xorm:"DATETIME deleted"` } assertSync(t, new(TbUserInfo)) @@ -964,7 +965,7 @@ func TestUpdateMapCondition(t *testing.T) { cnt, err := testEngine.Update(&UpdateMapCondition{ String: "string1", - }, map[string]interface{}{ + }, map[string]any{ "id": c.Id, }) assert.NoError(t, err) @@ -1000,7 +1001,7 @@ func TestUpdateMapContent(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 18, c.Age) - cnt, err := testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{"age": 0}) + cnt, err := testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]any{"age": 0}) assert.NoError(t, err) assert.EqualValues(t, 1, cnt) @@ -1010,7 +1011,7 @@ func TestUpdateMapContent(t *testing.T) { assert.True(t, has) assert.EqualValues(t, 0, c1.Age) - cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{ + cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]any{ "age": 16, "is_man": false, "gender": 2, @@ -1026,7 +1027,7 @@ func TestUpdateMapContent(t *testing.T) { assert.EqualValues(t, false, c2.IsMan) assert.EqualValues(t, 2, c2.Gender) - cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]interface{}{ + cnt, err = testEngine.Table(new(UpdateMapContent)).ID(c.Id).Update(map[string]any{ "age": 15, "is_man": true, "gender": 1, @@ -1143,7 +1144,7 @@ func TestUpdateDeleted(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 0, cnt) - cnt, err = testEngine.Table(&UpdateDeletedStruct{}).ID(s.Id).Update(map[string]interface{}{ + cnt, err = testEngine.Table(&UpdateDeletedStruct{}).ID(s.Id).Update(map[string]any{ "name": "test1", }) assert.NoError(t, err) @@ -1287,13 +1288,13 @@ func TestUpdateMap3(t *testing.T) { assertSync(t, new(UpdateMapUser)) - _, err := testEngine.Table(new(UpdateMapUser)).Insert(map[string]interface{}{ + _, err := testEngine.Table(new(UpdateMapUser)).Insert(map[string]any{ "Fname": "first user name", "Fver": 1, }) assert.NoError(t, err) - update := map[string]interface{}{ + update := map[string]any{ "Fname": "user name", "Fver": 1, } @@ -1301,7 +1302,7 @@ func TestUpdateMap3(t *testing.T) { assert.NoError(t, err) assert.EqualValues(t, 1, rows) - update = map[string]interface{}{ + update = map[string]any{ "Name": "user name", "Ver": 1, } @@ -1375,10 +1376,10 @@ func TestUpdateMultiplePK(t *testing.T) { assert.EqualValues(t, 1, num) test.Value = "4" - _, err = testEngine.ID([]interface{}{test.Id, test.Name}).Update(test) + _, err = testEngine.ID([]any{test.Id, test.Name}).Update(test) assert.NoError(t, err) - type MySlice []interface{} + type MySlice []any test.Value = "5" _, err = testEngine.ID(&MySlice{test.Id, test.Name}).Update(test) assert.NoError(t, err) diff --git a/tests/tags_test.go b/tests/tags_test.go index 14803462..6e28277a 100644 --- a/tests/tags_test.go +++ b/tests/tags_test.go @@ -10,11 +10,12 @@ import ( "testing" "time" + "xorm.io/xorm/v2/convert" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" + "github.com/stretchr/testify/assert" - "xorm.io/xorm/convert" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" ) type tempUser struct { @@ -507,30 +508,6 @@ func TestExtends5(t *testing.T) { } } -func TestCacheTag(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - type CacheDomain struct { - Id int64 `xorm:"pk cache"` - Name string - } - - assert.NoError(t, testEngine.CreateTables(&CacheDomain{})) - assert.True(t, testEngine.GetCacher(testEngine.TableName(&CacheDomain{})) != nil) -} - -func TestNoCacheTag(t *testing.T) { - assert.NoError(t, PrepareEngine()) - - type NoCacheDomain struct { - Id int64 `xorm:"pk nocache"` - Name string - } - - assert.NoError(t, testEngine.CreateTables(&NoCacheDomain{})) - assert.True(t, testEngine.GetCacher(testEngine.TableName(&NoCacheDomain{})) == nil) -} - type IDGonicMapper struct { ID int64 } diff --git a/tests/tests.go b/tests/tests.go index 220e1c67..bcb70e78 100644 --- a/tests/tests.go +++ b/tests/tests.go @@ -13,12 +13,12 @@ import ( "strings" "testing" - "xorm.io/xorm" - "xorm.io/xorm/caches" - "xorm.io/xorm/dialects" - "xorm.io/xorm/log" - "xorm.io/xorm/names" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + + "xorm.io/xorm/v2/dialects" + "xorm.io/xorm/v2/log" + "xorm.io/xorm/v2/names" + "xorm.io/xorm/v2/schemas" ) var ( @@ -30,7 +30,6 @@ var ( showSQL = flag.Bool("show_sql", true, "show generated SQLs") ptrConnStr = flag.String("conn_str", "./test.db?cache=shared&mode=rwc", "test database connection string") mapType = flag.String("map_type", "snake", "indicate the name mapping") - cacheFlag = flag.Bool("cache", false, "if enable cache") cluster = flag.Bool("cluster", false, "if this is a cluster") splitter = flag.String("splitter", ";", "the splitter on connstr for cluster") schema = flag.String("schema", "", "specify the schema") @@ -112,7 +111,7 @@ func createEngine(dbType, connStr string) error { testEngine, err = xorm.NewEngine(dbType, connStr) } else { testEngine, err = xorm.NewEngineGroup(dbType, strings.Split(connStr, *splitter)) - if dbType != "mysql" && dbType != "mymysql" { + if dbType != "mysql" { *ignoreSelectUpdate = true } } @@ -125,10 +124,6 @@ func createEngine(dbType, connStr string) error { } testEngine.ShowSQL(*showSQL) testEngine.SetLogLevel(log.LOG_DEBUG) - if *cacheFlag { - cacher := caches.NewLRUCacher(caches.NewMemoryStore(), 100000) - testEngine.SetDefaultCacher(cacher) - } if len(*mapType) > 0 { switch *mapType { @@ -162,7 +157,7 @@ func createEngine(dbType, connStr string) error { if err != nil { return err } - tableNames := make([]interface{}, 0, len(tables)) + tableNames := make([]any, 0, len(tables)) for _, table := range tables { tableNames = append(tableNames, table.Name) } diff --git a/tests/time_test.go b/tests/time_test.go index 13b9ed15..fab79491 100644 --- a/tests/time_test.go +++ b/tests/time_test.go @@ -11,9 +11,8 @@ import ( "testing" "time" - "xorm.io/xorm/convert" - - "xorm.io/xorm/internal/utils" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/utils" "github.com/stretchr/testify/assert" ) diff --git a/tests/types_null_test.go b/tests/types_null_test.go index d4fa250e..c407a5f8 100644 --- a/tests/types_null_test.go +++ b/tests/types_null_test.go @@ -35,7 +35,7 @@ func (CustomStruct) String() string { return "CustomStruct" } -func (m *CustomStruct) Scan(value interface{}) error { +func (m *CustomStruct) Scan(value any) error { if value == nil { m.Year, m.Month, m.Day = 0, 0, 0 return nil @@ -261,7 +261,7 @@ func TestNullStructIterate(t *testing.T) { if true { err := testEngine.Where("`age` IS NOT NULL").OrderBy("age").Iterate(new(NullStruct), - func(i int, bean interface{}) error { + func(i int, bean any) error { nultype := bean.(*NullStruct) fmt.Println(i, nultype) return nil diff --git a/tests/types_test.go b/tests/types_test.go index dfdb4766..17cc9cc4 100644 --- a/tests/types_test.go +++ b/tests/types_test.go @@ -12,10 +12,10 @@ import ( "strconv" "testing" - "xorm.io/xorm" - "xorm.io/xorm/convert" - "xorm.io/xorm/internal/json" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2" + "xorm.io/xorm/v2/internal/convert" + "xorm.io/xorm/v2/internal/json" + "xorm.io/xorm/v2/schemas" "github.com/stretchr/testify/assert" ) diff --git a/session_tx.go b/tx.go similarity index 70% rename from session_tx.go rename to tx.go index 4fa56891..ca54c741 100644 --- a/session_tx.go +++ b/tx.go @@ -4,10 +4,31 @@ package xorm +import ( + "hash/crc32" + + "xorm.io/xorm/v2/internal/core" +) + +func (session *Session) doPrepareTx(sqlStr string) (stmt *core.Stmt, err error) { + crc := crc32.ChecksumIEEE([]byte(sqlStr)) + // TODO try hash(sqlStr+len(sqlStr)) + var has bool + stmt, has = session.txStmtCache[crc] + if !has { + stmt, err = session.tx.PrepareContext(session.ctx, sqlStr) + if err != nil { + return nil, err + } + session.txStmtCache[crc] = stmt + } + return +} + // Begin a transaction func (session *Session) Begin() error { if session.isAutoCommit { - tx, err := session.DB().BeginTx(session.ctx, nil) + tx, err := session.db().BeginTx(session.ctx, nil) if err != nil { return err } @@ -44,7 +65,7 @@ func (session *Session) Commit() error { } // handle processors after tx committed - closureCallFunc := func(closuresPtr *[]func(interface{}), bean interface{}) { + closureCallFunc := func(closuresPtr *[]func(any), bean any) { if closuresPtr != nil { for _, closure := range *closuresPtr { closure(bean) @@ -55,27 +76,27 @@ func (session *Session) Commit() error { for bean, closuresPtr := range session.afterInsertBeans { closureCallFunc(closuresPtr, bean) - if processor, ok := interface{}(bean).(AfterInsertProcessor); ok { + if processor, ok := any(bean).(AfterInsertProcessor); ok { processor.AfterInsert() } } for bean, closuresPtr := range session.afterUpdateBeans { closureCallFunc(closuresPtr, bean) - if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok { + if processor, ok := any(bean).(AfterUpdateProcessor); ok { processor.AfterUpdate() } } for bean, closuresPtr := range session.afterDeleteBeans { closureCallFunc(closuresPtr, bean) - if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok { + if processor, ok := any(bean).(AfterDeleteProcessor); ok { processor.AfterDelete() } } - cleanUpFunc := func(slices *map[interface{}]*[]func(interface{})) { + cleanUpFunc := func(slices *map[any]*[]func(any)) { if len(*slices) > 0 { - *slices = make(map[interface{}]*[]func(interface{})) + *slices = make(map[any]*[]func(any)) } } cleanUpFunc(&session.afterInsertBeans) diff --git a/session_update.go b/update.go similarity index 87% rename from session_update.go rename to update.go index b3640ad2..77aae507 100644 --- a/session_update.go +++ b/update.go @@ -8,9 +8,9 @@ import ( "reflect" "xorm.io/builder" - "xorm.io/xorm/internal/statements" - "xorm.io/xorm/internal/utils" - "xorm.io/xorm/schemas" + "xorm.io/xorm/v2/internal/statements" + "xorm.io/xorm/v2/internal/utils" + "xorm.io/xorm/v2/schemas" ) // enumerated all errors @@ -18,12 +18,12 @@ var ( ErrNoColumnsTobeUpdated = statements.ErrNoColumnsTobeUpdated ) -func (session *Session) genAutoCond(condiBean interface{}) (builder.Cond, error) { +func (session *Session) genAutoCond(condiBean any) (builder.Cond, error) { if session.statement.NoAutoCondition { return builder.NewCond(), nil } - if c, ok := condiBean.(map[string]interface{}); ok { + if c, ok := condiBean.(map[string]any); ok { eq := make(builder.Eq) for k, v := range c { eq[session.engine.Quote(k)] = v @@ -60,7 +60,7 @@ func (session *Session) genAutoCond(condiBean interface{}) (builder.Cond, error) // 1.bool will defaultly be updated content nor conditions // You should call UseBool if you have bool to use. // 2.float32 & float64 may be not inexact as conditions -func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int64, error) { +func (session *Session) Update(bean any, condiBean ...any) (int64, error) { if session.isAutoClose { defer session.Close() } @@ -79,13 +79,13 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 closure(bean) } cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used - if processor, ok := interface{}(bean).(BeforeUpdateProcessor); ok { + if processor, ok := any(bean).(BeforeUpdateProcessor); ok { processor.BeforeUpdate() } // -- var colNames []string - var args []interface{} + var args []any var err error isMap := t.Kind() == reflect.Map isStruct := t.Kind() == reflect.Struct @@ -109,7 +109,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } } else if isMap { colNames = make([]string, 0) - args = make([]interface{}, 0) + args = make([]any, 0) bValue := reflect.Indirect(reflect.ValueOf(bean)) for _, v := range bValue.MapKeys() { @@ -139,7 +139,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 colName := col.Name if isStruct { - session.afterClosures = append(session.afterClosures, func(bean interface{}) { + session.afterClosures = append(session.afterClosures, func(bean any) { col := table.GetColumn(colName) setColumnTime(bean, col, t) }) @@ -191,7 +191,6 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } tableName := session.statement.TableName() // table name must been get before exec because statement will be reset - useCache := session.statement.UseCache res, err := session.exec(updateWriter.String(), updateWriter.Args()...) if err != nil { @@ -202,18 +201,12 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } } - if cacher := session.engine.GetCacher(tableName); cacher != nil && useCache { - session.engine.logger.Debugf("[cache] clear table: %v", tableName) - cacher.ClearIds(tableName) - cacher.ClearBeans(tableName) - } - // handle after update processors if session.isAutoCommit { for _, closure := range session.afterClosures { closure(bean) } - if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok { + if processor, ok := any(bean).(AfterUpdateProcessor); ok { session.engine.logger.Debugf("[event] %v has after update processor", tableName) processor.AfterUpdate() } @@ -223,13 +216,13 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if value, has := session.afterUpdateBeans[bean]; has && value != nil { *value = append(*value, session.afterClosures...) } else { - afterClosures := make([]func(interface{}), lenAfterClosures) + afterClosures := make([]func(any), lenAfterClosures) copy(afterClosures, session.afterClosures) // FIXME: if bean is a map type, it will panic because map cannot be as map key session.afterUpdateBeans[bean] = &afterClosures } } else { - if _, ok := interface{}(bean).(AfterUpdateProcessor); ok { + if _, ok := any(bean).(AfterUpdateProcessor); ok { session.afterUpdateBeans[bean] = nil } } @@ -240,10 +233,10 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 return res.RowsAffected() } -func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interface{}, error) { +func (session *Session) genUpdateColumns(bean any) ([]string, []any, error) { table := session.statement.RefTable colNames := make([]string, 0, len(table.ColumnsSeq())) - args := make([]interface{}, 0, len(table.ColumnsSeq())) + args := make([]any, 0, len(table.ColumnsSeq())) for _, col := range table.Columns() { if !col.IsVersion && !col.IsCreated && !col.IsUpdated { @@ -299,7 +292,7 @@ func (session *Session) genUpdateColumns(bean interface{}) ([]string, []interfac args = append(args, val) colName := col.Name - session.afterClosures = append(session.afterClosures, func(bean interface{}) { + session.afterClosures = append(session.afterClosures, func(bean any) { col := table.GetColumn(colName) setColumnTime(bean, col, t) })