Compare commits

...

22 Commits

Author SHA1 Message Date
Lunny Xiao 076858c1e5 Merge branch 'main' into lunny/postgres_for_update 2024-01-22 08:11:31 +00:00
Lunny Xiao 3344b42b4b Fix #2393 (#2395) (#2396)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2395
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2396
2024-01-15 14:51:06 +00:00
Lunny Xiao 15c64a9dfb
Fix readme links 2024-01-05 09:46:39 +08:00
Lunny Xiao 0852f43870 Fix test-mssql bug (#2391)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2391
2024-01-01 01:21:40 +00:00
Lunny Xiao f1391d7b2f Use github.com/microsoft/go-mssqldb instead of old mssqldb repository (#2386)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2386
2023-12-31 15:29:01 +00:00
Lunny Xiao 2a4161d7a5 Fix mssql get indexes bug when collation is not default with collation test for mssql (#2387)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2387
2023-12-31 14:07:15 +00:00
Lunny Xiao 81c3905773 Implement update join (#2383)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2383
2023-12-30 10:21:39 +00:00
Lunny Xiao b23798dc98 Fix time test (#2362)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2362
2023-10-30 05:21:09 +00:00
Lunny Xiao a4f9c21c17 Some refactors (#2361)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2361
2023-10-28 11:59:16 +00:00
Lunny Xiao 4cde28ca21 Use any instead of interface{} (#2360)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2360
2023-10-28 10:59:32 +00:00
Lunny Xiao 65977c35a4 some small refactors (#2357)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2357
2023-10-28 07:05:12 +00:00
Lunny Xiao 607f715634 Move convert internal (#2355)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2355
2023-10-28 03:30:11 +00:00
Lunny Xiao af9edecff1 Move core internal (#2354)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2354
2023-10-27 16:27:33 +00:00
Lunny Xiao 42553b7477 Remove cache features (#2347)
The cache feature is not used frequently but needs more time to maintain.
I think there are many machism to handle the cache out of ORM. So let's remove it.

Reviewed-on: https://gitea.com/xorm/xorm/pulls/2347
2023-10-27 15:48:07 +00:00
Lunny Xiao 82faf6c301 start v2 (#2350)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2350
2023-10-27 14:27:46 +00:00
Lunny Xiao 3b4c1be57a cache tools (#2353)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2353
2023-10-27 13:58:13 +00:00
Lunny Xiao 05a8643056 Remove mymysql driver since it's unmaintained for a long time (#2349)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2349
2023-10-27 09:21:35 +00:00
Lunny Xiao 8eeb1ef8ac Some refactors (#2348)
Reviewed-on: https://gitea.com/xorm/xorm/pulls/2348
2023-10-27 09:16:46 +00:00
Lunny Xiao a8d7033c06
Fix cockroach service 2023-10-25 18:12:15 +08:00
Lunny Xiao 2bafcc01e4
upgrade version again 2023-10-25 17:42:11 +08:00
Lunny Xiao c8fdd41310
upgrade cockraochdb version on ci 2023-10-25 17:28:18 +08:00
Lunny Xiao 8e2fda467f
enable for update test for postgres 2023-10-25 15:37:00 +08:00
141 changed files with 1696 additions and 3356 deletions

View File

@ -5,6 +5,9 @@ on:
tags: tags:
- '*' - '*'
env:
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
test-cockroach: test-cockroach:
@ -48,9 +49,10 @@ jobs:
services: services:
cockroach: cockroach:
image: cockroachdb/cockroach:v19.2.4 image: cockroachdb/cockroach:v23.1.11
ports: ports:
- 26257:26257 - 26257:26257
cmd: cmd:
- 'start' # - '/cockroach/cockroach.sh'
- 'start-single-node'
- '--insecure' - '--insecure'

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
lint: lint:

View File

@ -0,0 +1,58 @@
name: test mssql
on:
push:
branches:
- master
pull_request:
env:
GOPROXY: https://goproxy.io,direct
GOPATH: /go_path
GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs:
test-mssql-collation:
name: test mssql with collation
runs-on: ubuntu-latest
steps:
# - name: cache go path
# id: cache-go-path
# uses: https://github.com/actions/cache@v3
# with:
# path: /go_path
# key: go_path-${{ github.repository }}-${{ github.ref_name }}
# restore-keys: |
# go_path-${{ github.repository }}-
# go_path-
# - name: cache go cache
# id: cache-go-cache
# uses: https://github.com/actions/cache@v3
# with:
# path: /go_cache
# key: go_cache-${{ github.repository }}-${{ github.ref_name }}
# restore-keys: |
# go_cache-${{ github.repository }}-
# go_cache-
- uses: actions/setup-go@v3
with:
go-version: 1.20
- uses: actions/checkout@v3
- name: test mssql with collation
env:
TEST_MSSQL_HOST: mssql2
TEST_MSSQL_DBNAME: xorm_test
TEST_MSSQL_USERNAME: sa
TEST_MSSQL_PASSWORD: "yourStrong(!)Password"
TEST_MSSQL_COLLATION: SQL_Latin1_General_CP1_CS_AS
run: TEST_MSSQL_DEFAULT_VARCHAR=NVARCHAR TEST_MSSQL_DEFAULT_CHAR=NCHAR make test-mssql
services:
mssql2:
image: mcr.microsoft.com/mssql/server:latest
env:
ACCEPT_EULA: Y
SA_PASSWORD: yourStrong(!)Password
MSSQL_PID: Standard
ports:
- 1433:1433

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
test-mssql: test-mssql:

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
test-mysql: test-mysql:

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
lint: lint:

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
lint: lint:

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
test-sqlite: test-sqlite:

View File

@ -9,6 +9,7 @@ env:
GOPROXY: https://goproxy.io,direct GOPROXY: https://goproxy.io,direct
GOPATH: /go_path GOPATH: /go_path
GOCACHE: /go_cache GOCACHE: /go_cache
RUNNER_TOOL_CACHE: /toolcache # specify with your cache path
jobs: jobs:
test-tidb: test-tidb:

View File

@ -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 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 ### Patch review
Help review existing open [pull requests](https://gitea.com/xorm/xorm/pulls) by commenting on the code or Help review existing open [pull requests](https://gitea.com/xorm/xorm/pulls) by commenting on the code or

109
Makefile
View File

@ -6,10 +6,10 @@ GOFMT ?= gofmt -s
TAGS ?= TAGS ?=
SED_INPLACE := sed -i 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 := $(wildcard *.go)
GOFILES += $(shell find $(GO_DIRS) -name "*.go" -type f) 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 ./...)) PACKAGES ?= $(filter-out $(INTEGRATION_PACKAGES),$(shell $(GO) list ./...))
TEST_COCKROACH_HOST ?= cockroach:26257 TEST_COCKROACH_HOST ?= cockroach:26257
@ -25,6 +25,7 @@ TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
TEST_MSSQL_DEFAULT_VARCHAR ?= varchar TEST_MSSQL_DEFAULT_VARCHAR ?= varchar
TEST_MSSQL_DEFAULT_CHAR ?= char TEST_MSSQL_DEFAULT_CHAR ?= char
TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST ?= true TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST ?= true
TEST_MSSQL_COLLATION ?=
TEST_MYSQL_HOST ?= mysql:3306 TEST_MYSQL_HOST ?= mysql:3306
TEST_MYSQL_CHARSET ?= utf8 TEST_MYSQL_CHARSET ?= utf8
@ -47,7 +48,6 @@ TEST_DAMENG_HOST ?= dameng:5236
TEST_DAMENG_USERNAME ?= SYSDBA TEST_DAMENG_USERNAME ?= SYSDBA
TEST_DAMENG_PASSWORD ?= SYSDBA TEST_DAMENG_PASSWORD ?= SYSDBA
TEST_CACHE_ENABLE ?= false
TEST_QUOTE_POLICY ?= always TEST_QUOTE_POLICY ?= always
.PHONY: all .PHONY: all
@ -60,7 +60,7 @@ build: go-check $(GO_SOURCES)
.PHONY: clean .PHONY: clean
clean: clean:
$(GO) clean -i ./... $(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 .PHONY: coverage
coverage: coverage:
@ -137,145 +137,134 @@ test: go-check
.PNONY: test-cockroach .PNONY: test-cockroach
test-cockroach: go-check 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" \ -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\#% .PHONY: test-cockroach\#%
test-cockroach\#%: go-check 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" \ -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 .PNONY: test-mssql
test-mssql: go-check 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)" \ -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) \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \
-do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \
-coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -collation=$(TEST_MSSQL_COLLATION) \
-coverprofile=mssql.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PNONY: test-mssql\#% .PNONY: test-mssql\#%
test-mssql\#%: go-check 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)" \ -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) \ -default_varchar=$(TEST_MSSQL_DEFAULT_VARCHAR) -default_char=$(TEST_MSSQL_DEFAULT_CHAR) \
-do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \ -do_nvarchar_override_test=$(TEST_MSSQL_DO_NVARCHAR_OVERRIDE_TEST) \
-coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -coverprofile=mssql.$(TEST_QUOTE_POLICY).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
.PNONY: test-mysql .PNONY: test-mysql
test-mysql: go-check 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)" \ -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\#% .PHONY: test-mysql\#%
test-mysql\#%: go-check 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)" \ -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 .PNONY: test-mysql-tls
test-mysql-tls: go-check 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" \ -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\#% .PHONY: test-mysql-tls\#%
test-mysql-tls\#%: go-check 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" \ -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 .PNONY: test-postgres
test-postgres: go-check 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" \ -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\#% .PHONY: test-postgres\#%
test-postgres\#%: go-check 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" \ -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 .PHONY: test-sqlite3
test-sqlite3: go-check test-sqlite3: go-check
$(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PHONY: test-sqlite3-schema .PHONY: test-sqlite3-schema
test-sqlite3-schema: go-check 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" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PHONY: test-sqlite3\#% .PHONY: test-sqlite3\#%
test-sqlite3\#%: go-check 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" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite3.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PNONY: test-pgx .PNONY: test-pgx
test-pgx: go-check 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" \ -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\#% .PHONY: test-pgx\#%
test-pgx\#%: go-check 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" \ -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 .PHONY: test-sqlite
test-sqlite: go-check test-sqlite: go-check
$(GO) test $(INTEGRATION_PACKAGES) -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite -conn_str="./test.db?cache=shared&mode=rwc" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PHONY: test-sqlite-schema .PHONY: test-sqlite-schema
test-sqlite-schema: go-check 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" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -timeout=20m -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic -timeout=20m
.PHONY: test-sqlite\#% .PHONY: test-sqlite\#%
test-sqlite\#%: go-check 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" \ $(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).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic -quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).coverage.out -covermode=atomic
.PNONY: test-tidb .PNONY: test-tidb
test-tidb: go-check 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)" \ -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\#% .PHONY: test-tidb\#%
test-tidb\#%: go-check 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)" \ -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 .PNONY: test-dameng
test-dameng: go-check 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)" \ -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\#% .PHONY: test-dameng\#%
test-dameng\#%: go-check 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)" \ -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 .PHONY: vet
vet: vet:

View File

@ -1,6 +1,6 @@
# xorm # xorm
[中文](https://gitea.com/xorm/xorm/src/branch/master/README_CN.md) [中文](https://gitea.com/xorm/xorm/src/branch/main/README_CN.md)
Xorm is a simple and powerful ORM for Go. Xorm is a simple and powerful ORM for Go.
@ -21,7 +21,6 @@ v1.0.0 has some break changes from v0.8.2.
* Transaction Support * Transaction Support
* Both ORM and raw SQL operation Support * Both ORM and raw SQL operation Support
* Sync database schema Support * Sync database schema Support
* Query Cache speed up
* Database Reverse support via [xorm.io/reverse](https://xorm.io/reverse) * Database Reverse support via [xorm.io/reverse](https://xorm.io/reverse)
* Simple cascade loading support * Simple cascade loading support
* Optimistic Locking 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) * [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/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) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach)
- [github.com/lib/pq](https://github.com/lib/pq) - [github.com/lib/pq](https://github.com/lib/pq)
@ -48,7 +46,7 @@ Drivers for Go's sql package which currently support database/sql includes:
- [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) - [modernc.org/sqlite](https://gitlab.com/cznic/sqlite)
* MsSql * MsSql
- [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) - [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb)
* Oracle * Oracle
- [github.com/godror/godror](https://github.com/godror/godror) (experiment) - [github.com/godror/godror](https://github.com/godror/godror) (experiment)
@ -57,13 +55,13 @@ Drivers for Go's sql package which currently support database/sql includes:
## Installation ## Installation
go get xorm.io/xorm go get xorm.io/xorm/v2
## Documents ## Documents
* [Manual](http://xorm.io/docs) * [Manual](http://xorm.io/docs)
* [GoDoc](http://pkg.go.dev/xorm.io/xorm) * [GoDoc](http://pkg.go.dev/xorm.io/xorm/v2)
## Quick Start ## Quick Start
@ -107,7 +105,7 @@ engineGroup, err := xorm.NewEngineGroup(masterEngine, []*Engine{slave1Engine, sl
Then all place where `engine` you can just use `engineGroup`. 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 ```Go
results, err := engine.Query("select * from user") results, err := engine.Query("select * from user")
@ -143,13 +141,13 @@ affected, err := engine.Insert(&user1, &users)
// INSERT INTO struct1 () values () // INSERT INTO struct1 () values ()
// INSERT INTO struct2 () 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", "name": "lunny",
"age": 18, "age": 18,
}) })
// INSERT INTO user (name, age) values (?,?) // 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", "name": "lunny",
"age": 18, "age": 18,
@ -189,7 +187,7 @@ var valuesMap = make(map[string]string)
has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap) has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ? // 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) has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ? // 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 * `Iterate` and `Rows` query multiple records and record by record handle, there are two methods Iterate and Rows
```Go ```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) user := bean.(*User)
return nil return nil
}) })
// SELECT * FROM user // 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) user := bean.(*User)
return nil return nil
}) })
@ -416,7 +414,7 @@ return session.Commit()
* Or you can use `Transaction` to replace above codes. * Or you can use `Transaction` to replace above codes.
```Go ```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()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil { if _, err := session.Insert(&user1); err != nil {
return nil, err return nil, err
@ -490,20 +488,18 @@ You can find all the changelog [here](CHANGELOG.md)
## Cases ## Cases
* [studygolang](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang) * [Gitea](http://about.gitea.com) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea)
* [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)
* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) * [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) * [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader)
* [Wego](http://github.com/go-tango/wego) * [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) * [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) * [Gorevel](http://gorevel.cn/) - [github.com/goofcc/gorevel](http://github.com/goofcc/gorevel)

View File

@ -1,6 +1,6 @@
# xorm # xorm
[English](https://gitea.com/xorm/xorm/src/branch/master/README.md) [English](https://gitea.com/xorm/xorm/src/branch/main/README.md)
xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
@ -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) * [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/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) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach)
- [github.com/lib/pq](https://github.com/lib/pq) - [github.com/lib/pq](https://github.com/lib/pq)
@ -47,7 +46,7 @@ v1.0.0 相对于 v0.8.2 有以下不兼容的变更:
- [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) - [modernc.org/sqlite](https://gitlab.com/cznic/sqlite)
* MsSql * MsSql
- [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) - [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb)
* Oracle * Oracle
- [github.com/godror/godror](https://github.com/godror/godror) (试验性支持) - [github.com/godror/godror](https://github.com/godror/godror) (试验性支持)
@ -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) * [操作指南](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` 来替换。 所有使用 `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 ```Go
results, err := engine.Query("select * from user") results, err := engine.Query("select * from user")
@ -140,13 +139,13 @@ affected, err := engine.Insert(&user1, &users)
// INSERT INTO struct1 () values () // INSERT INTO struct1 () values ()
// INSERT INTO struct2 () 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", "name": "lunny",
"age": 18, "age": 18,
}) })
// INSERT INTO user (name, age) values (?,?) // 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", "name": "lunny",
"age": 18, "age": 18,
@ -186,7 +185,7 @@ var valuesMap = make(map[string]string)
has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap) has, err := engine.Table(&user).Where("id = ?", id).Get(&valuesMap)
// SELECT * FROM user WHERE id = ? // 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) has, err := engine.Table(&user).Where("id = ?", id).Cols(cols...).Get(&valuesSlice)
// SELECT col1, col2, col3 FROM user WHERE id = ? // SELECT col1, col2, col3 FROM user WHERE id = ?
``` ```
@ -243,13 +242,13 @@ err := engine.Table("user").Select("user.*, detail.*").
* `Iterate``Rows` 根据条件遍历数据库,可以有两种方式: Iterate and Rows * `Iterate``Rows` 根据条件遍历数据库,可以有两种方式: Iterate and Rows
```Go ```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) user := bean.(*User)
return nil return nil
}) })
// SELECT * FROM user // 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) user := bean.(*User)
return nil return nil
}) })
@ -406,7 +405,7 @@ return session.Commit()
* 事务的简写方法 * 事务的简写方法
```Go ```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()} user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
if _, err := session.Insert(&user1); err != nil { if _, err := session.Insert(&user1); err != nil {
return nil, err return nil, err

View File

@ -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 : <tablename>-p-<pk1>-<pk2>...
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-<pk1>-<pk2>...
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)
}

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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()}
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -9,10 +9,10 @@ import (
"strings" "strings"
"time" "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) v, err := col.ValueOf(bean)
if err != nil { if err != nil {
return 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) v, err := col.ValueOf(bean)
if err != nil { if err != nil {
return 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" // 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...) session.statement.Incr(column, arg...)
return session return session
} }
// Decr provides a query string like "count = count - 1" // 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...) session.statement.Decr(column, arg...)
return session return session
} }
// SetExpr provides a query string like "column = {expression}" // 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) session.statement.SetExpr(column, expression)
return session return session
} }
@ -115,9 +115,7 @@ func (session *Session) UseBool(columns ...string) *Session {
return session return session
} }
// Distinct use for distinct columns. Caution: when you are using cache, // Distinct use for distinct columns.
// distinct will not be cached because cache system need id,
// but distinct will not provide id
func (session *Session) Distinct(columns ...string) *Session { func (session *Session) Distinct(columns ...string) *Session {
session.statement.Distinct(columns...) session.statement.Distinct(columns...)
return session return session

View File

@ -8,43 +8,43 @@ import "xorm.io/builder"
// SQL provides raw sql input parameter. When you have a complex SQL statement // 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. // 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...) session.statement.SQL(query, args...)
return session return session
} }
// Where provides custom query condition. // 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...) session.statement.Where(query, args...)
return session return session
} }
// And provides custom query condition. // 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...) session.statement.And(query, args...)
return session return session
} }
// Or provides custom query condition. // 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...) session.statement.Or(query, args...)
return session return session
} }
// ID provides converting id as a query condition // 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) session.statement.ID(id)
return session return session
} }
// In provides a query string like "id in (1, 2, 3)" // 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...) session.statement.In(column, args...)
return session return session
} }
// NotIn provides a query string like "id in (1, 2, 3)" // 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...) session.statement.NotIn(column, args...)
return session return session
} }

View File

@ -7,24 +7,24 @@ package contexts
// ContextCache is the interface that operates the cache data. // ContextCache is the interface that operates the cache data.
type ContextCache interface { type ContextCache interface {
// Put puts value into cache with key. // 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 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 // NewMemoryContextCache return memoryContextCache
func NewMemoryContextCache() memoryContextCache { func NewMemoryContextCache() memoryContextCache {
return make(map[string]interface{}) return make(map[string]any)
} }
// Put puts value into cache with key. // 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 m[key] = val
} }
// Get gets cached value by given key. // Get gets cached value by given key.
func (m memoryContextCache) Get(key string) interface{} { func (m memoryContextCache) Get(key string) any {
return m[key] return m[key]
} }

View File

@ -14,15 +14,15 @@ import (
type ContextHook struct { type ContextHook struct {
start time.Time start time.Time
Ctx context.Context Ctx context.Context
SQL string // log content or SQL SQL string // log content or SQL
Args []interface{} // if it's a SQL, it's the arguments Args []any // if it's a SQL, it's the arguments
Result sql.Result Result sql.Result
ExecuteTime time.Duration ExecuteTime time.Duration
Err error // SQL executed error Err error // SQL executed error
} }
// NewContextHook return context for hook // 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{ return &ContextHook{
start: time.Now(), start: time.Now(),
Ctx: ctx, Ctx: ctx,

121
delete.go Normal file
View File

@ -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()
}

View File

@ -13,10 +13,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
func init() { func init() {
@ -749,14 +749,14 @@ func (db *dameng) SetQuotePolicy(quotePolicy QuotePolicy) {
} }
} }
func (db *dameng) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { func (db *dameng) IndexCheckSQL(tableName, idxName string) (string, []any) {
args := []interface{}{tableName, idxName} args := []any{tableName, idxName}
return `SELECT INDEX_NAME FROM USER_INDEXES ` + return `SELECT INDEX_NAME FROM USER_INDEXES ` +
`WHERE TABLE_NAME = ? AND INDEX_NAME = ?`, args `WHERE TABLE_NAME = ? AND INDEX_NAME = ?`, args
} }
func (db *dameng) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { func (db *dameng) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) {
return db.HasRecords(queryer, ctx, `SELECT table_name FROM user_tables WHERE table_name = ?`, tableName) 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) { 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 return cnt > 0, nil
} }
func (db *dameng) IsColumnExist(queryer core.Queryer, ctx context.Context, tableName, colName string) (bool, error) { func (db *dameng) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) {
args := []interface{}{tableName, colName} args := []any{tableName, colName}
query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = ?" + query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = ?" +
" AND column_name = ?" " AND column_name = ?"
return db.HasRecords(queryer, ctx, query, args...) return db.HasRecords(ctx, queryer, query, args...)
} }
var _ sql.Scanner = &dmClobScanner{} var _ sql.Scanner = &dmClobScanner{}
@ -800,7 +800,7 @@ type dmClobObject interface {
// var _ dmClobObject = &dm.DmClob{} // var _ dmClobObject = &dm.DmClob{}
func (d *dmClobScanner) Scan(data interface{}) error { func (d *dmClobScanner) Scan(data any) error {
if data == nil { if data == nil {
return nil return nil
} }
@ -850,7 +850,7 @@ func addSingleQuote(name string) string {
return b.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 s := `select column_name from user_cons_columns
where constraint_name = (select constraint_name from user_constraints where constraint_name = (select constraint_name from user_constraints
where table_name = ? and constraint_type ='P')` 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 { if utils.IndexSlice(pkNames, col.Name) > -1 {
col.IsPrimaryKey = true 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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1002,9 +1002,9 @@ func (db *dameng) GetColumns(queryer core.Queryer, ctx context.Context, tableNam
return colSeq, cols, nil 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 ?" 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...) rows, err := queryer.QueryContext(ctx, s, args...)
if err != nil { if err != nil {
@ -1028,8 +1028,8 @@ func (db *dameng) GetTables(queryer core.Queryer, ctx context.Context) ([]*schem
return tables, nil return tables, nil
} }
func (db *dameng) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { func (db *dameng) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName, tableName} args := []any{tableName, tableName}
s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + 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 =?" + "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 = ?)" " 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 }, nil
} }
func (d *damengDriver) GenScanResult(colType string) (interface{}, error) { func (d *damengDriver) GenScanResult(colType string) (any, error) {
switch colType { switch colType {
case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB": case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB":
var s sql.NullString 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 { func (d *damengDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.ColumnType, vv ...any) error {
scanResults := make([]interface{}, 0, len(types)) scanResults := make([]any, 0, len(types))
replaces := make([]bool, 0, len(types)) replaces := make([]bool, 0, len(types))
var err error var err error
for i, v := range vv { for i, v := range vv {
var replaced bool var replaced bool
var scanResult interface{} var scanResult any
switch types[i].DatabaseTypeName() { switch types[i].DatabaseTypeName() {
case "CLOB", "TEXT": case "CLOB", "TEXT":
scanResult = &dmClobScanner{} scanResult = &dmClobScanner{}
@ -1179,7 +1179,7 @@ func (d *damengDriver) Scan(ctx *ScanContext, rows *core.Rows, types []*sql.Colu
if replaced { if replaced {
switch t := scanResults[i].(type) { switch t := scanResults[i].(type) {
case *dmClobScanner: case *dmClobScanner:
var d interface{} var d any
if t.valid { if t.valid {
d = t.data d = t.data
} else { } else {

View File

@ -10,8 +10,8 @@ import (
"strings" "strings"
"time" "time"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// URI represents an uri to visit database // URI represents an uri to visit database
@ -66,13 +66,13 @@ type Dialect interface {
AutoIncrStr() string AutoIncrStr() string
GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error)
IndexCheckSQL(tableName, idxName string) (string, []interface{}) IndexCheckSQL(tableName, idxName string) (string, []any)
CreateIndexSQL(tableName string, index *schemas.Index) string CreateIndexSQL(tableName string, index *schemas.Index) string
DropIndexSQL(tableName string, index *schemas.Index) string DropIndexSQL(tableName string, index *schemas.Index) string
GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error)
IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, 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) CreateTableSQL(ctx context.Context, queryer core.Queryer, table *schemas.Table, tableName string) (string, bool, error)
DropTableSQL(tableName string) (string, bool) DropTableSQL(tableName string) (string, bool)
@ -80,8 +80,8 @@ type Dialect interface {
IsSequenceExist(ctx context.Context, queryer core.Queryer, seqName string) (bool, error) IsSequenceExist(ctx context.Context, queryer core.Queryer, seqName string) (bool, error)
DropSequenceSQL(seqName string) (string, error) DropSequenceSQL(seqName string) (string, error)
GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error)
IsColumnExist(queryer core.Queryer, ctx context.Context, tableName string, colName string) (bool, error) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName string, colName string) (bool, error)
AddColumnSQL(tableName string, col *schemas.Column) string AddColumnSQL(tableName string, col *schemas.Column) string
ModifyColumnSQL(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 // 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...) rows, err := queryer.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return false, err 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 // 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 quote := db.dialect.Quoter().Quote
query := fmt.Sprintf( query := fmt.Sprintf(
"SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?", "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("TABLE_NAME"),
quote("COLUMN_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 // 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{} }}, "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 "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{} }}, "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{} }}, "postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }},
"pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }}, "pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }},
"sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }}, "sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }},

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"time" "time"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
) )
// ScanContext represents a context when Scan // ScanContext represents a context when Scan
@ -27,13 +27,11 @@ type DriverFeatures struct {
type Driver interface { type Driver interface {
Parse(string, string) (*URI, error) Parse(string, string) (*URI, error)
Features() *DriverFeatures Features() *DriverFeatures
GenScanResult(string) (interface{}, error) // according given column type generating a suitable scan interface GenScanResult(string) (any, error) // according given column type generating a suitable scan interface
Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...interface{}) error Scan(*ScanContext, *core.Rows, []*sql.ColumnType, ...any) error
} }
var ( var drivers = map[string]Driver{}
drivers = map[string]Driver{}
)
// RegisterDriver register a driver // RegisterDriver register a driver
func RegisterDriver(driverName string, driver Driver) { func RegisterDriver(driverName string, driver Driver) {
@ -80,6 +78,6 @@ func OpenDialect(driverName, connstr string) (Dialect, error) {
type baseDriver struct{} 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...) return rows.Scan(v...)
} }

View File

@ -13,8 +13,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( var (
@ -442,25 +442,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) return fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s", db.quoter.Quote(tableName), s)
} }
func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []any) {
args := []interface{}{idxName} args := []any{idxName}
sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?" sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?"
return sql, args 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" = ?` 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" 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) { func (db *mssql) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{} args := []any{}
s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable, 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), "default_is_null" = (CASE WHEN c.text is null THEN 1 ELSE 0 END),
replace(replace(isnull(c.text,''),'(',''),')','') as vdefault, replace(replace(isnull(c.text,''),'(',''),')','') as vdefault,
@ -553,8 +553,8 @@ func (db *mssql) GetColumns(queryer core.Queryer, ctx context.Context, tableName
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { func (db *mssql) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) {
args := []interface{}{} args := []any{}
s := `select name from sysobjects where xtype ='U'` s := `select name from sysobjects where xtype ='U'`
rows, err := queryer.QueryContext(ctx, s, args...) rows, err := queryer.QueryContext(ctx, s, args...)
@ -580,16 +580,16 @@ func (db *mssql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schema
return tables, nil return tables, nil
} }
func (db *mssql) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { func (db *mssql) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []any{tableName}
s := `SELECT s := `SELECT
IXS.NAME AS [INDEX_NAME], IXS.NAME AS [INDEX_NAME],
C.NAME AS [COLUMN_NAME], C.NAME AS [COLUMN_NAME],
IXS.is_unique AS [IS_UNIQUE] IXS.is_unique AS [IS_UNIQUE]
FROM SYS.INDEXES IXS FROM sys.indexes IXS
INNER JOIN SYS.INDEX_COLUMNS IXCS INNER JOIN sys.index_columns IXCS
ON IXS.OBJECT_ID=IXCS.OBJECT_ID AND IXS.INDEX_ID = IXCS.INDEX_ID ON IXS.OBJECT_ID=IXCS.OBJECT_ID AND IXS.INDEX_ID = IXCS.INDEX_ID
INNER JOIN SYS.COLUMNS C ON IXS.OBJECT_ID=C.OBJECT_ID INNER JOIN sys.columns C ON IXS.OBJECT_ID=C.OBJECT_ID
AND IXCS.COLUMN_ID=C.COLUMN_ID AND IXCS.COLUMN_ID=C.COLUMN_ID
WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =? WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
` `
@ -719,7 +719,7 @@ func (p *odbcDriver) Parse(driverName, dataSourceName string) (*URI, error) {
return &URI{DBName: dbName, DBType: schemas.MSSQL}, nil 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 { switch colType {
case "VARCHAR", "TEXT", "CHAR", "NVARCHAR", "NCHAR", "NTEXT": case "VARCHAR", "TEXT", "CHAR", "NVARCHAR", "NCHAR", "NTEXT":
fallthrough fallthrough

View File

@ -12,10 +12,9 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"time"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( var (
@ -371,16 +370,16 @@ func (db *mysql) AutoIncrStr() string {
return "AUTO_INCREMENT" return "AUTO_INCREMENT"
} }
func (db *mysql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { func (db *mysql) IndexCheckSQL(tableName, idxName string) (string, []any) {
args := []interface{}{db.uri.DBName, tableName, idxName} args := []any{db.uri.DBName, tableName, idxName}
sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`" sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`"
sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?" sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?"
return sql, args 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`=?" 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 { 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) 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) { func (db *mysql) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{db.uri.DBName, tableName} args := []any{db.uri.DBName, tableName}
alreadyQuoted := "(INSTR(VERSION(), 'maria') > 0 && " + alreadyQuoted := "(INSTR(VERSION(), 'maria') > 0 && " +
"(SUBSTRING_INDEX(VERSION(), '.', 1) > 10 || " + "(SUBSTRING_INDEX(VERSION(), '.', 1) > 10 || " +
"(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 return colSeq, cols, nil
} }
func (db *mysql) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { func (db *mysql) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) {
args := []interface{}{db.uri.DBName} args := []any{db.uri.DBName}
s := "SELECT `TABLE_NAME`, `ENGINE`, `AUTO_INCREMENT`, `TABLE_COMMENT`, `TABLE_COLLATION` from " + 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')" "`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) { func (db *mysql) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{db.uri.DBName, tableName} 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`" 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...) rows, err := queryer.QueryContext(ctx, s, args...)
@ -760,7 +759,7 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) {
return uri, nil 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) colType = strings.Replace(colType, "UNSIGNED ", "", -1)
switch colType { switch colType {
case "CHAR", "VARCHAR", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "ENUM", "SET", "JSON": 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 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
}

View File

@ -13,8 +13,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( 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) { 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) { 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{}) { func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []any) {
args := []interface{}{tableName, idxName} args := []any{tableName, idxName}
return `SELECT INDEX_NAME FROM USER_INDEXES ` + return `SELECT INDEX_NAME FROM USER_INDEXES ` +
`WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args `WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args
} }
func (db *oracle) IsTableExist(queryer core.Queryer, ctx context.Context, tableName string) (bool, error) { func (db *oracle) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) {
return db.HasRecords(queryer, ctx, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName) 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) { func (db *oracle) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) {
args := []interface{}{tableName, colName} args := []any{tableName, colName}
query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" + query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" +
" AND column_name = :2" " 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) { func (db *oracle) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []any{tableName}
s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," + s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
"nullable FROM USER_TAB_COLUMNS WHERE table_name = :1" "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 return colSeq, cols, nil
} }
func (db *oracle) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { func (db *oracle) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) {
args := []interface{}{} args := []any{}
s := "SELECT table_name FROM user_tables" s := "SELECT table_name FROM user_tables"
rows, err := queryer.QueryContext(ctx, s, args...) 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 return tables, nil
} }
func (db *oracle) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { func (db *oracle) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []any{tableName}
s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + 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" "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 return db, nil
} }
func (g *godrorDriver) GenScanResult(colType string) (interface{}, error) { func (g *godrorDriver) GenScanResult(colType string) (any, error) {
switch colType { switch colType {
case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB": case "CHAR", "NCHAR", "VARCHAR", "VARCHAR2", "NVARCHAR2", "LONG", "CLOB", "NCLOB":
var s sql.NullString var s sql.NullString

View File

@ -13,8 +13,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html // from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
@ -998,23 +998,23 @@ func (db *postgres) AutoIncrStr() string {
return "" return ""
} }
func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []any) {
if len(db.getSchema()) == 0 { if len(db.getSchema()) == 0 {
args := []interface{}{tableName, idxName} args := []any{tableName, idxName}
return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args 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 ` + return `SELECT indexname FROM pg_indexes ` +
`WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args `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 { 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) 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)) 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) { func (db *postgres) IsColumnExist(ctx context.Context, queryer core.Queryer, tableName, colName string) (bool, error) {
args := []interface{}{db.getSchema(), tableName, colName} args := []any{db.getSchema(), tableName, colName}
query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" + query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" +
" AND column_name = $3" " AND column_name = $3"
if len(db.getSchema()) == 0 { 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" + query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
" AND column_name = $2" " AND column_name = $2"
} }
@ -1092,8 +1092,8 @@ func (db *postgres) IsColumnExist(queryer core.Queryer, ctx context.Context, tab
return false, rows.Err() return false, rows.Err()
} }
func (db *postgres) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { func (db *postgres) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []any{tableName}
s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, description, 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 = 'p' THEN true ELSE false END AS primarykey,
CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey 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 return colSeq, cols, nil
} }
func (db *postgres) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { func (db *postgres) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) {
args := []interface{}{} args := []any{}
s := "SELECT tablename FROM pg_tables" s := "SELECT tablename FROM pg_tables"
schema := db.getSchema() schema := db.getSchema()
if schema != "" { if schema != "" {
@ -1288,8 +1288,8 @@ func getIndexColName(indexdef string) []string {
return colNames return colNames
} }
func (db *postgres) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { func (db *postgres) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []any{tableName}
s := "SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1" s := "SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1"
if len(db.getSchema()) != 0 { if len(db.getSchema()) != 0 {
args = append(args, db.getSchema()) args = append(args, db.getSchema())
@ -1522,7 +1522,7 @@ func (p *pqDriver) Parse(driverName, dataSourceName string) (*URI, error) {
return db, nil return db, nil
} }
func (p *pqDriver) GenScanResult(colType string) (interface{}, error) { func (p *pqDriver) GenScanResult(colType string) (any, error) {
switch colType { switch colType {
case "VARCHAR", "TEXT": case "VARCHAR", "TEXT":
var s sql.NullString var s sql.NullString

View File

@ -12,8 +12,8 @@ import (
"regexp" "regexp"
"strings" "strings"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( var (
@ -267,13 +267,13 @@ func (db *sqlite3) AutoIncrStr() string {
return "AUTOINCREMENT" return "AUTOINCREMENT"
} }
func (db *sqlite3) IndexCheckSQL(tableName, idxName string) (string, []interface{}) { func (db *sqlite3) IndexCheckSQL(tableName, idxName string) (string, []any) {
args := []interface{}{idxName} args := []any{idxName}
return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args 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) { func (db *sqlite3) IsTableExist(ctx context.Context, queryer core.Queryer, tableName string) (bool, error) {
return db.HasRecords(queryer, ctx, "SELECT name FROM sqlite_master WHERE type='table' and name = ?", tableName) 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 { 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)) 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" query := "SELECT * FROM " + tableName + " LIMIT 0"
rows, err := queryer.QueryContext(ctx, query) rows, err := queryer.QueryContext(ctx, query)
if err != nil { if err != nil {
@ -375,8 +375,8 @@ func parseString(colStr string) (*schemas.Column, error) {
return col, nil return col, nil
} }
func (db *sqlite3) GetColumns(queryer core.Queryer, ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) { func (db *sqlite3) GetColumns(ctx context.Context, queryer core.Queryer, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []any{tableName}
s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?" s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?"
rows, err := queryer.QueryContext(ctx, s, args...) 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 return colSeq, cols, nil
} }
func (db *sqlite3) GetTables(queryer core.Queryer, ctx context.Context) ([]*schemas.Table, error) { func (db *sqlite3) GetTables(ctx context.Context, queryer core.Queryer) ([]*schemas.Table, error) {
args := []interface{}{} args := []any{}
s := "SELECT name FROM sqlite_master WHERE type='table'" s := "SELECT name FROM sqlite_master WHERE type='table'"
rows, err := queryer.QueryContext(ctx, s, args...) 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 return tables, nil
} }
func (db *sqlite3) GetIndexes(queryer core.Queryer, ctx context.Context, tableName string) (map[string]*schemas.Index, error) { func (db *sqlite3) GetIndexes(ctx context.Context, queryer core.Queryer, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []any{tableName}
s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?" s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?"
rows, err := queryer.QueryContext(ctx, s, args...) 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 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 { switch colType {
case "TEXT": case "TEXT":
var s sql.NullString var s sql.NullString

View File

@ -9,9 +9,9 @@ import (
"reflect" "reflect"
"strings" "strings"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/names" "xorm.io/xorm/v2/names"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// TableNameWithSchema will add schema prefix on table name if possible // 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 // 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 quote := dialect.Quoter().Quote
switch tt := tableName.(type) { switch tt := tableName.(type) {
case []string: case []string:
@ -37,7 +37,7 @@ func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName interface
} else if len(tt) == 1 { } else if len(tt) == 1 {
return quote(tt[0]) return quote(tt[0])
} }
case []interface{}: case []any:
l := len(tt) l := len(tt)
var table string var table string
if l > 0 { 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 // 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) tbName := TableNameNoSchema(dialect, mapper, bean)
if len(includeSchema) > 0 && includeSchema[0] && !utils.IsSubQuery(tbName) { if len(includeSchema) > 0 && includeSchema[0] && !utils.IsSubQuery(tbName) {
tbName = TableNameWithSchema(dialect, tbName) tbName = TableNameWithSchema(dialect, tbName)

View File

@ -7,7 +7,7 @@ package dialects
import ( import (
"testing" "testing"
"xorm.io/xorm/names" "xorm.io/xorm/v2/names"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -8,11 +8,11 @@ import (
"strings" "strings"
"time" "time"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// FormatColumnTime format column time // 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 t.IsZero() { if t.IsZero() {
if col.Nullable { if col.Nullable {
return nil, nil return nil, nil

View File

@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
type dialect struct { type dialect struct {
@ -31,7 +31,7 @@ func TestFormatColumnTime(t *testing.T) {
location *time.Location location *time.Location
column *schemas.Column column *schemas.Column
time time.Time time time.Time
wantRes interface{} wantRes any
wantErr error wantErr error
}{ }{
{ {

4
doc.go
View File

@ -32,7 +32,7 @@ XORM supports raw SQL execution:
results, err := engine.QueryString("select * from user") 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") 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, 4. Query multiple records and record by record handle, there two methods, one is Iterate,
another is Rows 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 // do something
}) })
// SELECT * FROM user // SELECT * FROM user

216
engine.go
View File

@ -17,21 +17,19 @@ import (
"strings" "strings"
"time" "time"
"xorm.io/xorm/caches" "xorm.io/xorm/v2/contexts"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/log"
"xorm.io/xorm/log" "xorm.io/xorm/v2/names"
"xorm.io/xorm/names" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/tags"
"xorm.io/xorm/tags"
) )
// Engine is the major struct of xorm, it means a database manager. // Engine is the major struct of xorm, it means a database manager.
// Commonly, an application only need one engine // Commonly, an application only need one engine
type Engine struct { type Engine struct {
cacherMgr *caches.Manager
defaultContext context.Context defaultContext context.Context
dialect dialects.Dialect dialect dialects.Dialect
driver dialects.Driver 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) { func newEngine(driverName, dataSourceName string, dialect dialects.Dialect, db *core.DB) (*Engine, error) {
cacherMgr := caches.NewManager()
mapper := names.NewCacheMapper(new(names.SnakeMapper)) mapper := names.NewCacheMapper(new(names.SnakeMapper))
tagParser := tags.NewParser("xorm", dialect, mapper, mapper, cacherMgr) tagParser := tags.NewParser("xorm", dialect, mapper, mapper)
engine := &Engine{ engine := &Engine{
dialect: dialect, dialect: dialect,
driver: dialects.QueryDriver(driverName), driver: dialects.QueryDriver(driverName),
TZLocation: time.Local, TZLocation: time.Local,
defaultContext: context.Background(), defaultContext: context.Background(),
cacherMgr: cacherMgr,
tagParser: tagParser, tagParser: tagParser,
driverName: driverName, driverName: driverName,
dataSourceName: dataSourceName, dataSourceName: dataSourceName,
@ -129,16 +125,6 @@ func (engine *Engine) EnableSessionID(enable bool) {
engine.logSessionID = enable 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 // SetQuotePolicy sets the special quote policy
func (engine *Engine) SetQuotePolicy(quotePolicy dialects.QuotePolicy) { func (engine *Engine) SetQuotePolicy(quotePolicy dialects.QuotePolicy) {
engine.dialect.SetQuotePolicy(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 // ShowSQL show SQL statement or not on logger if log level is great than INFO
func (engine *Engine) ShowSQL(show ...bool) { func (engine *Engine) ShowSQL(show ...bool) {
engine.logger.ShowSQL(show...) engine.logger.ShowSQL(show...)
engine.DB().Logger = engine.logger engine.db.Logger = engine.logger
} }
// Logger return the logger interface // Logger return the logger interface
@ -163,7 +149,7 @@ func (engine *Engine) Logger() log.ContextLogger {
} }
// SetLogger set the new logger // SetLogger set the new logger
func (engine *Engine) SetLogger(logger interface{}) { func (engine *Engine) SetLogger(logger any) {
var realLogger log.ContextLogger var realLogger log.ContextLogger
switch t := logger.(type) { switch t := logger.(type) {
case log.ContextLogger: case log.ContextLogger:
@ -174,7 +160,7 @@ func (engine *Engine) SetLogger(logger interface{}) {
panic("logger should implement either log.ContextLogger or log.Logger") panic("logger should implement either log.ContextLogger or log.Logger")
} }
engine.logger = realLogger engine.logger = realLogger
engine.DB().Logger = realLogger engine.db.Logger = realLogger
} }
// SetLogLevel sets the logger level // SetLogLevel sets the logger level
@ -182,11 +168,6 @@ func (engine *Engine) SetLogLevel(level log.LogLevel) {
engine.logger.SetLevel(level) 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 // DriverName return the current sql driver's name
func (engine *Engine) DriverName() string { func (engine *Engine) DriverName() string {
return engine.driverName 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. // SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (engine *Engine) SetConnMaxLifetime(d time.Duration) { 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. // SetConnMaxIdleTime sets the maximum amount of time a connection may be idle.
func (engine *Engine) SetConnMaxIdleTime(d time.Duration) { func (engine *Engine) SetConnMaxIdleTime(d time.Duration) {
engine.DB().SetConnMaxIdleTime(d) engine.db.SetConnMaxIdleTime(d)
} }
// SetMaxOpenConns is only available for go 1.2+ // SetMaxOpenConns is only available for go 1.2+
func (engine *Engine) SetMaxOpenConns(conns int) { 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 // SetMaxIdleConns set the max idle connections on pool, default is 2
func (engine *Engine) SetMaxIdleConns(conns int) { func (engine *Engine) SetMaxIdleConns(conns int) {
engine.DB().SetMaxIdleConns(conns) 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()
} }
// NoCascade If you do not want to auto cascade load object // NoCascade If you do not want to auto cascade load object
@ -294,22 +257,6 @@ func (engine *Engine) NoCascade() *Session {
return session.NoCascade() 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 // Dialect return database dialect
func (engine *Engine) Dialect() dialects.Dialect { func (engine *Engine) Dialect() dialects.Dialect {
return engine.dialect return engine.dialect
@ -322,7 +269,7 @@ func (engine *Engine) NewSession() *Session {
// Close the engine // Close the engine
func (engine *Engine) Close() error { func (engine *Engine) Close() error {
return engine.DB().Close() return engine.db.Close()
} }
// Ping tests if database is alive // Ping tests if database is alive
@ -338,7 +285,7 @@ func (engine *Engine) Ping() error {
// engine.SQL("select * from user").Find(&users) // engine.SQL("select * from user").Find(&users)
// //
// This code will execute "select * from user" and set the records to 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.SQL(query, args...) 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 { 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 { if err != nil {
return err return err
} }
for _, name := range colSeq { for _, name := range colSeq {
table.AddColumn(cols[name]) 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 { if err != nil {
return err 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. // DBMetas Retrieve all tables, columns, indexes' informations from database.
func (engine *Engine) DBMetas() ([]*schemas.Table, error) { 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 { if err != nil {
return nil, err return nil, err
} }
@ -481,8 +428,7 @@ func (engine *Engine) dumpTables(ctx context.Context, tables []*schemas.Table, w
return err return err
} }
} }
cacherMgr := caches.NewManager() dstTableCache := tags.NewParser("xorm", dstDialect, engine.GetTableMapper(), engine.GetColumnMapper())
dstTableCache := tags.NewParser("xorm", dstDialect, engine.GetTableMapper(), engine.GetColumnMapper(), cacherMgr)
_, err := io.WriteString(w, fmt.Sprintf("/*Generated by xorm %s, from %s to %s*/\n\n", _, 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)) 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, ", ") colNames := engine.dialect.Quoter().Join(cols, ", ")
destColNames := dstDialect.Quoter().Join(dstCols, ", ") 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 { if err != nil {
return err return err
} }
@ -835,28 +781,28 @@ func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
} }
// Where method provide a condition query // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Where(query, args...) return session.Where(query, args...)
} }
// ID method provoide a condition as (id) = ? // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.ID(id) return session.ID(id)
} }
// Before apply before Processor, affected bean is passed to closure arg // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Before(closures) return session.Before(closures)
} }
// After apply after insert Processor, affected bean is passed to closure arg // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.After(closures) return session.After(closures)
@ -876,9 +822,7 @@ func (engine *Engine) StoreEngine(storeEngine string) *Session {
return session.StoreEngine(storeEngine) return session.StoreEngine(storeEngine)
} }
// Distinct use for distinct columns. Caution: when you are using cache, // Distinct use for distinct columns.
// distinct will not be cached because cache system need id,
// but distinct will not provide id
func (engine *Engine) Distinct(columns ...string) *Session { func (engine *Engine) Distinct(columns ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
@ -939,42 +883,42 @@ func (engine *Engine) Nullable(columns ...string) *Session {
} }
// In will generate "column IN (?, ?)" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.In(column, args...) return session.In(column, args...)
} }
// NotIn will generate "column NOT IN (?, ?)" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.NotIn(column, args...) return session.NotIn(column, args...)
} }
// Incr provides a update string like "column = column + ?" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Incr(column, arg...) return session.Incr(column, arg...)
} }
// Decr provides a update string like "column = column - ?" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Decr(column, arg...) return session.Decr(column, arg...)
} }
// SetExpr provides a update string like "column = {expression}" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.SetExpr(column, expression) return session.SetExpr(column, expression)
} }
// Table temporarily change the Get, Find, Update's table // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Table(tableNameOrBean) return session.Table(tableNameOrBean)
@ -1013,7 +957,7 @@ func (engine *Engine) Asc(colNames ...string) *Session {
} }
// OrderBy will generate "ORDER BY order" // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.OrderBy(order, args...) 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 // 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 := engine.NewSession()
session.isAutoClose = true session.isAutoClose = true
return session.Join(joinOperator, tablename, condition, args...) 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 // 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) v := utils.ReflectValue(bean)
return engine.tagParser.ParseWithCache(v) return engine.tagParser.ParseWithCache(v)
} }
// IsTableEmpty if a table has any reocrd // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.IsTableEmpty(bean) return session.IsTableEmpty(bean)
} }
// IsTableExist if a table is exist // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.IsTableExist(beanOrTableName) return session.IsTableExist(beanOrTableName)
} }
// TableName returns table name with schema prefix if has // 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...) return dialects.FullTableName(engine.dialect, engine.GetTableMapper(), bean, includeSchema...)
} }
// CreateIndexes create indexes // CreateIndexes create indexes
func (engine *Engine) CreateIndexes(bean interface{}) error { func (engine *Engine) CreateIndexes(bean any) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.CreateIndexes(bean) return session.CreateIndexes(bean)
} }
// CreateUniques create uniques // CreateUniques create uniques
func (engine *Engine) CreateUniques(bean interface{}) error { func (engine *Engine) CreateUniques(bean any) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.CreateUniques(bean) 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 // UnMapType remove table from tables cache
func (engine *Engine) UnMapType(t reflect.Type) { func (engine *Engine) UnMapType(t reflect.Type) {
engine.tagParser.ClearCacheTable(t) engine.tagParser.ClearCacheTable(t)
} }
// CreateTables create tabls according bean // CreateTables create tabls according bean
func (engine *Engine) CreateTables(beans ...interface{}) error { func (engine *Engine) CreateTables(beans ...any) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1141,7 +1061,7 @@ func (engine *Engine) CreateTables(beans ...interface{}) error {
} }
// DropTables drop specify tables // DropTables drop specify tables
func (engine *Engine) DropTables(beans ...interface{}) error { func (engine *Engine) DropTables(beans ...any) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1161,49 +1081,49 @@ func (engine *Engine) DropTables(beans ...interface{}) error {
} }
// DropIndexes drop indexes of a table // DropIndexes drop indexes of a table
func (engine *Engine) DropIndexes(bean interface{}) error { func (engine *Engine) DropIndexes(bean any) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.DropIndexes(bean) return session.DropIndexes(bean)
} }
// Exec raw sql // Exec raw sql
func (engine *Engine) Exec(sqlOrArgs ...interface{}) (sql.Result, error) { func (engine *Engine) Exec(sqlOrArgs ...any) (sql.Result, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Exec(sqlOrArgs...) return session.Exec(sqlOrArgs...)
} }
// Query a raw sql and return records as []map[string][]byte // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Query(sqlOrArgs...) return session.Query(sqlOrArgs...)
} }
// QueryString runs a raw sql and return records as []map[string]string // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.QueryString(sqlOrArgs...) return session.QueryString(sqlOrArgs...)
} }
// QueryInterface runs a raw sql and return records as []map[string]interface{} // QueryInterface runs a raw sql and return records as []map[string]any
func (engine *Engine) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) { func (engine *Engine) QueryInterface(sqlOrArgs ...any) ([]map[string]any, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.QueryInterface(sqlOrArgs...) return session.QueryInterface(sqlOrArgs...)
} }
// Insert one or more records // Insert one or more records
func (engine *Engine) Insert(beans ...interface{}) (int64, error) { func (engine *Engine) Insert(beans ...any) (int64, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Insert(beans...) return session.Insert(beans...)
} }
// InsertOne insert only one record // InsertOne insert only one record
func (engine *Engine) InsertOne(bean interface{}) (int64, error) { func (engine *Engine) InsertOne(bean any) (int64, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.InsertOne(bean) return session.InsertOne(bean)
@ -1216,7 +1136,7 @@ func (engine *Engine) InsertOne(bean interface{}) (int64, error) {
// 1.bool will defaultly be updated content nor conditions // 1.bool will defaultly be updated content nor conditions
// You should call UseBool if you have bool to use. // You should call UseBool if you have bool to use.
// 2.float32 & float64 may be not inexact as conditions // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Update(bean, condiBeans...) 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 // Delete records, bean's non-empty fields are conditions
// At least one condition must be set. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Delete(beans...) 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 // Truncate records, bean's non-empty fields are conditions
// In contrast to Delete this method allows deletes without 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Truncate(beans...) 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 // Get retrieve one record from table, bean's non-empty fields
// are conditions // are conditions
func (engine *Engine) Get(beans ...interface{}) (bool, error) { func (engine *Engine) Get(beans ...any) (bool, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Get(beans...) return session.Get(beans...)
} }
// Exist returns true if the record exist otherwise return false // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Exist(bean...) 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 // Find retrieve records from table, condiBeans's non-empty fields
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct // are conditions. beans could be []Struct, []*Struct, map[int64]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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Find(beans, condiBeans...) return session.Find(beans, condiBeans...)
} }
// FindAndCount find the results and also return the counts // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.FindAndCount(rowsSlicePtr, condiBean...) 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 // Iterate record by record handle records from table, bean's non-empty fields
// are conditions. // are conditions.
func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error { func (engine *Engine) Iterate(bean any, fun IterFunc) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Iterate(bean, fun) 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 // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
// are conditions. // are conditions.
func (engine *Engine) Rows(bean interface{}) (*Rows, error) { func (engine *Engine) Rows(bean any) (*Rows, error) {
session := engine.NewSession() session := engine.NewSession()
return session.Rows(bean) return session.Rows(bean)
} }
// Count counts the records. bean's non-empty fields are conditions. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Count(bean...) return session.Count(bean...)
} }
// Sum sum the records by some column. bean's non-empty fields are conditions. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Sum(bean, colName) return session.Sum(bean, colName)
} }
// SumInt sum the records by some column. bean's non-empty fields are conditions. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.SumInt(bean, colName) return session.SumInt(bean, colName)
} }
// Sums sum the records by some columns. bean's non-empty fields are conditions. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Sums(bean, colNames...) return session.Sums(bean, colNames...)
} }
// SumsInt like Sums but return slice of int64 instead of float64. // 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() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.SumsInt(bean, colNames...) return session.SumsInt(bean, colNames...)
@ -1334,7 +1254,7 @@ func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
} }
// nowTime return current time // 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() t := time.Now()
result, err := dialects.FormatColumnTime(engine.dialect, engine.DatabaseTZ, col, t) result, err := dialects.FormatColumnTime(engine.dialect, engine.DatabaseTZ, col, t)
if err != nil { 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 // 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() session := engine.NewSession()
defer session.Close() defer session.Close()

View File

@ -8,11 +8,10 @@ import (
"context" "context"
"time" "time"
"xorm.io/xorm/caches" "xorm.io/xorm/v2/contexts"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/log"
"xorm.io/xorm/log" "xorm.io/xorm/v2/names"
"xorm.io/xorm/names"
) )
// EngineGroup defines an engine group // EngineGroup defines an engine group
@ -23,7 +22,7 @@ type EngineGroup struct {
} }
// NewEngineGroup creates a new engine group // 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 var eg EngineGroup
if len(policies) > 0 { if len(policies) > 0 {
eg.policy = 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 // SetLogger set the new logger
func (eg *EngineGroup) SetLogger(logger interface{}) { func (eg *EngineGroup) SetLogger(logger any) {
eg.Engine.SetLogger(logger) eg.Engine.SetLogger(logger)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetLogger(logger) 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 // SetMaxIdleConns set the max idle connections on pool, default is 2
func (eg *EngineGroup) SetMaxIdleConns(conns int) { func (eg *EngineGroup) SetMaxIdleConns(conns int) {
eg.Engine.DB().SetMaxIdleConns(conns) eg.Engine.db.SetMaxIdleConns(conns)
for i := 0; i < len(eg.slaves); i++ { 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+ // SetMaxOpenConns is only available for go 1.2+
func (eg *EngineGroup) SetMaxOpenConns(conns int) { func (eg *EngineGroup) SetMaxOpenConns(conns int) {
eg.Engine.DB().SetMaxOpenConns(conns) eg.Engine.db.SetMaxOpenConns(conns)
for i := 0; i < len(eg.slaves); i++ { 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 // 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 := eg.NewSession()
sess.isAutoClose = true sess.isAutoClose = true
return sess.Query(sqlOrArgs...) return sess.Query(sqlOrArgs...)
} }
// QueryInterface execcute a select SQL and return the result // 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 := eg.NewSession()
sess.isAutoClose = true sess.isAutoClose = true
return sess.QueryInterface(sqlOrArgs...) return sess.QueryInterface(sqlOrArgs...)
} }
// QueryString execcute a select SQL and return the result // 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 := eg.NewSession()
sess.isAutoClose = true sess.isAutoClose = true
return sess.QueryString(sqlOrArgs...) return sess.QueryString(sqlOrArgs...)
} }
// Rows execcute a select SQL and return the result // 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 := eg.NewSession()
sess.isAutoClose = true sess.isAutoClose = true
return sess.Rows(bean) return sess.Rows(bean)

View File

@ -25,7 +25,7 @@ func (h GroupPolicyHandler) Slave(eg *EngineGroup) *Engine {
// RandomPolicy implmentes randomly chose the slave of slaves // RandomPolicy implmentes randomly chose the slave of slaves
func RandomPolicy() GroupPolicyHandler { 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 func(g *EngineGroup) *Engine {
return g.Slaves()[r.Intn(len(g.Slaves()))] return g.Slaves()[r.Intn(len(g.Slaves()))]
} }
@ -33,16 +33,16 @@ func RandomPolicy() GroupPolicyHandler {
// WeightRandomPolicy implmentes randomly chose the slave of slaves // WeightRandomPolicy implmentes randomly chose the slave of slaves
func WeightRandomPolicy(weights []int) GroupPolicyHandler { 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 i := 0; i < len(weights); i++ {
for n := 0; n < weights[i]; n++ { for n := 0; n < weights[i]; n++ {
rands = append(rands, i) 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 { return func(g *EngineGroup) *Engine {
var slaves = g.Slaves() slaves := g.Slaves()
idx := rands[r.Intn(len(rands))] idx := rands[r.Intn(len(rands))]
if idx >= len(slaves) { if idx >= len(slaves) {
idx = len(slaves) - 1 idx = len(slaves) - 1
@ -53,10 +53,10 @@ func WeightRandomPolicy(weights []int) GroupPolicyHandler {
// RoundRobinPolicy returns a group policy handler // RoundRobinPolicy returns a group policy handler
func RoundRobinPolicy() GroupPolicyHandler { func RoundRobinPolicy() GroupPolicyHandler {
var pos = -1 pos := -1
var lock sync.Mutex var lock sync.Mutex
return func(g *EngineGroup) *Engine { return func(g *EngineGroup) *Engine {
var slaves = g.Slaves() slaves := g.Slaves()
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
@ -71,17 +71,17 @@ func RoundRobinPolicy() GroupPolicyHandler {
// WeightRoundRobinPolicy returns a group policy handler // WeightRoundRobinPolicy returns a group policy handler
func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler { 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 i := 0; i < len(weights); i++ {
for n := 0; n < weights[i]; n++ { for n := 0; n < weights[i]; n++ {
rands = append(rands, i) rands = append(rands, i)
} }
} }
var pos = -1 pos := -1
var lock sync.Mutex var lock sync.Mutex
return func(g *EngineGroup) *Engine { return func(g *EngineGroup) *Engine {
var slaves = g.Slaves() slaves := g.Slaves()
lock.Lock() lock.Lock()
defer lock.Unlock() defer lock.Unlock()
pos++ pos++
@ -100,11 +100,11 @@ func WeightRoundRobinPolicy(weights []int) GroupPolicyHandler {
// LeastConnPolicy implements GroupPolicy, every time will get the least connections slave // LeastConnPolicy implements GroupPolicy, every time will get the least connections slave
func LeastConnPolicy() GroupPolicyHandler { func LeastConnPolicy() GroupPolicyHandler {
return func(g *EngineGroup) *Engine { return func(g *EngineGroup) *Engine {
var slaves = g.Slaves() slaves := g.Slaves()
connections := 0 connections := 0
idx := 0 idx := 0
for i := 0; i < len(slaves); i++ { for i := 0; i < len(slaves); i++ {
openConnections := slaves[i].DB().Stats().OpenConnections openConnections := slaves[i].db.Stats().OpenConnections
if i == 0 { if i == 0 {
connections = openConnections connections = openConnections
idx = i idx = i

View File

@ -9,18 +9,14 @@ import (
) )
var ( var (
// ErrPtrSliceType represents a type error
ErrPtrSliceType = errors.New("A point to a slice is needed")
// ErrParamsType params error // ErrParamsType params error
ErrParamsType = errors.New("Params type error") ErrParamsType = errors.New("Params type error")
// ErrTableNotFound table not found error // ErrTableNotFound table not found error
ErrTableNotFound = errors.New("Table not found") ErrTableNotFound = errors.New("Table not found")
// ErrUnSupportedType unsupported error // ErrUnSupportedType unsupported error
ErrUnSupportedType = errors.New("Unsupported type 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 condition type unsupported
ErrConditionType = errors.New("Unsupported condition type") ErrConditionType = errors.New("Unsupported condition type")
) )

View File

@ -11,11 +11,10 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/caches"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/internal/statements" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/schemas"
) )
const ( const (
@ -26,7 +25,7 @@ const (
// Find retrieve records from table, condiBeans's non-empty fields // Find retrieve records from table, condiBeans's non-empty fields
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct // are conditions. beans could be []Struct, []*Struct, map[int64]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 { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
@ -34,7 +33,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
} }
// FindAndCount find the results and also return the counts // 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 { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
@ -78,7 +77,7 @@ func (session *Session) FindAndCount(rowsSlicePtr interface{}, condiBean ...inte
return session.Unscoped().Count() 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() defer session.resetStatement()
if session.statement.LastError != nil { if session.statement.LastError != nil {
return session.statement.LastError return session.statement.LastError
@ -148,18 +147,6 @@ func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{})
return err 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...) return session.noCacheFind(table, sliceValue, sqlStr, args...)
} }
@ -221,7 +208,7 @@ func ParseColumnsSchema(fieldNames []string, types []*sql.ColumnType, table *sch
return &columnsSchema 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() elemType := containerValue.Type().Elem()
var isPointer bool var isPointer bool
if elemType.Kind() == reflect.Ptr { if elemType.Kind() == reflect.Ptr {
@ -331,216 +318,3 @@ func (session *Session) noCacheFind(table *schemas.Table, containerValue reflect
} }
return rows.Err() 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
}

View File

@ -10,31 +10,27 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"reflect" "reflect"
"strconv"
"time" "time"
"xorm.io/xorm/caches" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/internal/core"
"xorm.io/xorm/core" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/schemas"
) )
var ( // ErrObjectIsNil return error of object is nil
// ErrObjectIsNil return error of object is nil var ErrObjectIsNil = errors.New("object should not be nil")
ErrObjectIsNil = errors.New("object should not be nil")
)
// Get retrieve one record from database, bean's non-empty fields // Get retrieve one record from database, bean's non-empty fields
// will be as conditions // will be as conditions
func (session *Session) Get(beans ...interface{}) (bool, error) { func (session *Session) Get(beans ...any) (bool, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
return session.get(beans...) return session.get(beans...)
} }
func isPtrOfTime(v interface{}) bool { func isPtrOfTime(v any) bool {
if _, ok := v.(*time.Time); ok { if _, ok := v.(*time.Time); ok {
return true return true
} }
@ -47,7 +43,7 @@ func isPtrOfTime(v interface{}) bool {
return el.Type().ConvertibleTo(schemas.TimeType) 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() defer session.resetStatement()
if session.statement.LastError != nil { if session.statement.LastError != nil {
@ -66,7 +62,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) {
return false, ErrObjectIsNil 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 isStruct {
if err := session.statement.SetRefBean(beans[0]); err != nil { if err := session.statement.SetRefBean(beans[0]); err != nil {
return false, err return false, err
@ -74,7 +70,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) {
} }
var sqlStr string var sqlStr string
var args []interface{} var args []any
var err error var err error
if session.statement.RawSQL == "" { if session.statement.RawSQL == "" {
@ -92,17 +88,6 @@ func (session *Session) get(beans ...interface{}) (bool, error) {
} }
table := session.statement.RefTable 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 context := session.statement.Context
if context != nil && isStruct { if context != nil && isStruct {
res := context.Get(fmt.Sprintf("%v-%v", sqlStr, args)) res := context.Get(fmt.Sprintf("%v-%v", sqlStr, args))
@ -129,7 +114,7 @@ func (session *Session) get(beans ...interface{}) (bool, error) {
return true, nil return true, nil
} }
func isScannableStruct(bean interface{}, typeLen int) bool { func isScannableStruct(bean any, typeLen int) bool {
switch bean.(type) { switch bean.(type) {
case *time.Time: case *time.Time:
return false return false
@ -143,7 +128,7 @@ func isScannableStruct(bean interface{}, typeLen int) bool {
return true 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...) rows, err := session.queryRows(sqlStr, args...)
if err != nil { if err != nil {
return false, err return false, err
@ -174,7 +159,7 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *schemas.Table,
return true, session.executeProcessors() 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 { if len(beans) == 1 {
bean := beans[0] bean := beans[0]
switch firstBeanKind { 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...) 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) { switch t := bean.(type) {
case *[]string: case *[]string:
res, err := session.engine.scanStringInterface(rows, fields, types) 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 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 { for i, r := range res {
if needAppend { if needAppend {
*t = append(*t, r.(*sql.NullString).String) *t = append(*t, r.(*sql.NullString).String)
@ -221,12 +206,12 @@ func (session *Session) getSlice(rows *core.Rows, types []*sql.ColumnType, field
} }
} }
return nil return nil
case *[]interface{}: case *[]any:
scanResults, err := session.engine.scanInterfaces(rows, fields, types) scanResults, err := session.engine.scanInterfaces(rows, fields, types)
if err != nil { if err != nil {
return err return err
} }
var needAppend = len(*t) == 0 needAppend := len(*t) == 0
for ii := range fields { for ii := range fields {
s, err := convert.Interface2Interface(session.engine.DatabaseTZ, scanResults[ii]) s, err := convert.Interface2Interface(session.engine.DatabaseTZ, scanResults[ii])
if err != nil { 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) { switch t := bean.(type) {
case *map[string]string: case *map[string]string:
scanResults, err := session.engine.scanStringInterface(rows, fields, types) 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 (*t)[key] = scanResults[ii].(*sql.NullString).String
} }
return nil return nil
case *map[string]interface{}: case *map[string]any:
scanResults, err := session.engine.scanInterfaces(rows, fields, types) scanResults, err := session.engine.scanInterfaces(rows, fields, types)
if err != nil { if err != nil {
return err 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) { // Exist returns true if the record exist otherwise return false
// if has no reftable, then don't use cache currently func (session *Session) Exist(bean ...any) (bool, error) {
if !session.canCache() { if session.isAutoClose {
return false, ErrCacheFailed defer session.Close()
} }
for _, filter := range session.engine.dialect.Filters() { if session.statement.LastError != nil {
sqlStr = filter.Do(session.ctx, sqlStr) return false, session.statement.LastError
}
newsql := session.statement.ConvertIDSQL(sqlStr)
if newsql == "" {
return false, ErrCacheFailed
} }
tableName := session.statement.TableName() sqlStr, args, err := session.statement.GenExistSQL(bean...)
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)
if err != nil { if err != nil {
var res = make([]string, len(table.PrimaryKeys)) return false, err
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)
} }
if len(ids) > 0 { rows, err := session.queryRows(sqlStr, args...)
structValue := reflect.Indirect(reflect.ValueOf(bean)) if err != nil {
id := ids[0] return false, err
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
} }
return false, nil defer rows.Close()
if rows.Next() {
return true, nil
}
return false, rows.Err()
} }

48
go.mod
View File

@ -1,21 +1,55 @@
module xorm.io/xorm module xorm.io/xorm/v2
go 1.16 go 1.20
require ( require (
gitee.com/travelliu/dm v1.8.11192 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/go-sql-driver/mysql v1.7.0
github.com/goccy/go-json v0.8.1 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/jackc/pgx/v4 v4.18.0
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.16 github.com/mattn/go-sqlite3 v1.14.16
github.com/microsoft/go-mssqldb v1.6.0
github.com/shopspring/decimal v1.3.1 github.com/shopspring/decimal v1.3.1
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.4
github.com/syndtr/goleveldb v1.0.0
github.com/ziutek/mymysql v1.5.4
modernc.org/sqlite v1.20.4 modernc.org/sqlite v1.20.4
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978
) )
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-20220223132316-b832511892a9 // 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.12.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/tools v0.6.0 // 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
)

110
go.sum
View File

@ -2,15 +2,15 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGq
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
gitee.com/travelliu/dm v1.8.11192 h1:aqJT0xhodZjRutIfEXxKYv0CxqmHUHzsbz6SFaRL6OY= gitee.com/travelliu/dm v1.8.11192 h1:aqJT0xhodZjRutIfEXxKYv0CxqmHUHzsbz6SFaRL6OY=
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4=
github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@ -19,12 +19,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
@ -34,28 +30,20 @@ github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI=
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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 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.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
@ -76,7 +64,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/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 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 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 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.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= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
@ -118,6 +105,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -131,20 +119,15 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc=
github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -174,15 +157,11 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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/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/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.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= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -200,38 +179,31 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -241,16 +213,14 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -261,8 +231,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@ -272,63 +243,38 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
modernc.org/cc/v3 v3.38.1/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI=
modernc.org/ccgo/v3 v3.0.0-20220910160915-348f15de615a/go.mod h1:8p47QxPkdugex9J4n9P2tLZ9bK01yngIVp00g4nomW0=
modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g=
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA=
modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0=
modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0= modernc.org/libc v1.22.2 h1:4U7v51GyhlWqQmwCHj28Rdq2Yzwk55ovjFrdPjs8Hb0=
modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ= modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk= modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.20.4 h1:J8+m2trkN+KKoE7jglyHYYYiaq5xmz2HoHJIiBlRzbE= modernc.org/sqlite v1.20.4 h1:J8+m2trkN+KKoE7jglyHYYYiaq5xmz2HoHJIiBlRzbE=
@ -336,10 +282,8 @@ modernc.org/sqlite v1.20.4/go.mod h1:zKcGyrICaxNTMEHSr1HQ2GUraP0j+845GYw37+EyT6A
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34= modernc.org/tcl v1.15.0 h1:oY+JeD11qVVSgVvodMJsu7Edf8tr5E/7tuhF5cNYz34=
modernc.org/tcl v1.15.0/go.mod h1:xRoGotBZ6dU+Zo2tca+2EqVEeMmOUBzHnhIwq4YrVnE=
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE= 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 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM=
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=

View File

@ -13,17 +13,20 @@ import (
"time" "time"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// ErrNoElementsOnSlice represents an error there is no element when insert // ErrNoElementsOnSlice represents an error there is no element when insert
var ErrNoElementsOnSlice = errors.New("no element on slice 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 // 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 affected int64
var err error var err error
@ -41,9 +44,9 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
var cnt int64 var cnt int64
var err error var err error
switch v := bean.(type) { switch v := bean.(type) {
case map[string]interface{}: case map[string]any:
cnt, err = session.insertMapInterface(v) cnt, err = session.insertMapInterface(v)
case []map[string]interface{}: case []map[string]any:
cnt, err = session.insertMultipleMapInterface(v) cnt, err = session.insertMultipleMapInterface(v)
case map[string]string: case map[string]string:
cnt, err = session.insertMapString(v) cnt, err = session.insertMapString(v)
@ -66,7 +69,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
return affected, err 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)) sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
if sliceValue.Kind() != reflect.Slice { if sliceValue.Kind() != reflect.Slice {
return 0, errors.New("needs a pointer to a 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() size = sliceValue.Len()
colNames []string colNames []string
colMultiPlaces []string colMultiPlaces []string
args []interface{} args []any
) )
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
@ -111,7 +114,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
closure(elemValue) closure(elemValue)
} }
if processor, ok := interface{}(elemValue).(BeforeInsertProcessor); ok { if processor, ok := any(elemValue).(BeforeInsertProcessor); ok {
processor.BeforeInsert() processor.BeforeInsert()
} }
// -- // --
@ -158,14 +161,14 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
args = append(args, val) args = append(args, val)
colName := col.Name colName := col.Name
session.afterClosures = append(session.afterClosures, func(bean interface{}) { session.afterClosures = append(session.afterClosures, func(bean any) {
col := table.GetColumn(colName) col := table.GetColumn(colName)
setColumnTime(bean, col, t) setColumnTime(bean, col, t)
}) })
} else if col.IsVersion && session.statement.CheckVersion { } else if col.IsVersion && session.statement.CheckVersion {
args = append(args, 1) args = append(args, 1)
colName := col.Name colName := col.Name
session.afterClosures = append(session.afterClosures, func(bean interface{}) { session.afterClosures = append(session.afterClosures, func(bean any) {
col := table.GetColumn(colName) col := table.GetColumn(colName)
setColumnInt(bean, col, 1) setColumnInt(bean, col, 1)
}) })
@ -197,8 +200,6 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
return 0, err return 0, err
} }
_ = session.cacheInsert(tableName)
lenAfterClosures := len(session.afterClosures) lenAfterClosures := len(session.afterClosures)
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().Interface() 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 { if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
*value = append(*value, session.afterClosures...) *value = append(*value, session.afterClosures...)
} else { } else {
afterClosures := make([]func(interface{}), lenAfterClosures) afterClosures := make([]func(any), lenAfterClosures)
copy(afterClosures, session.afterClosures) copy(afterClosures, session.afterClosures)
session.afterInsertBeans[elemValue] = &afterClosures session.afterInsertBeans[elemValue] = &afterClosures
} }
@ -234,7 +235,7 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
} }
// InsertMulti insert multiple records // InsertMulti insert multiple records
func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) { func (session *Session) InsertMulti(rowsSlicePtr any) (int64, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
@ -247,7 +248,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
return session.insertMultipleStruct(rowsSlicePtr) 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 { if err := session.statement.SetRefBean(bean); err != nil {
return 0, err return 0, err
} }
@ -261,7 +262,7 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) {
} }
cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok { if processor, ok := any(bean).(BeforeInsertProcessor); ok {
processor.BeforeInsert() processor.BeforeInsert()
} }
@ -279,12 +280,12 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) {
} }
sqlStr = session.engine.dialect.Quoter().Replace(sqlStr) sqlStr = session.engine.dialect.Quoter().Replace(sqlStr)
handleAfterInsertProcessorFunc := func(bean interface{}) { handleAfterInsertProcessorFunc := func(bean any) {
if session.isAutoCommit { if session.isAutoCommit {
for _, closure := range session.afterClosures { for _, closure := range session.afterClosures {
closure(bean) closure(bean)
} }
if processor, ok := interface{}(bean).(AfterInsertProcessor); ok { if processor, ok := any(bean).(AfterInsertProcessor); ok {
processor.AfterInsert() processor.AfterInsert()
} }
} else { } else {
@ -293,12 +294,12 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) {
if value, has := session.afterInsertBeans[bean]; has && value != nil { if value, has := session.afterInsertBeans[bean]; has && value != nil {
*value = append(*value, session.afterClosures...) *value = append(*value, session.afterClosures...)
} else { } else {
afterClosures := make([]func(interface{}), lenAfterClosures) afterClosures := make([]func(any), lenAfterClosures)
copy(afterClosures, session.afterClosures) copy(afterClosures, session.afterClosures)
session.afterInsertBeans[bean] = &afterClosures session.afterInsertBeans[bean] = &afterClosures
} }
} else { } else {
if _, ok := interface{}(bean).(AfterInsertProcessor); ok { if _, ok := any(bean).(AfterInsertProcessor); ok {
session.afterInsertBeans[bean] = nil 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 there is auto increment column and driver don't support return it
if len(table.AutoIncrement) > 0 && !session.engine.driver.Features().SupportReturnInsertedID { if len(table.AutoIncrement) > 0 && !session.engine.driver.Features().SupportReturnInsertedID {
var sql string var sql string
var newArgs []interface{} var newArgs []any
var needCommit bool var needCommit bool
var id int64 var id int64
if session.engine.dialect.URI().DBType == schemas.ORACLE || session.engine.dialect.URI().DBType == schemas.DAMENG { 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) defer handleAfterInsertProcessorFunc(bean)
_ = session.cacheInsert(tableName)
if table.Version != "" && session.statement.CheckVersion { if table.Version != "" && session.statement.CheckVersion {
verValue, err := table.VersionColumn().ValueOf(bean) verValue, err := table.VersionColumn().ValueOf(bean)
if err != nil { if err != nil {
@ -384,8 +383,6 @@ func (session *Session) insertStruct(bean interface{}) (int64, error) {
defer handleAfterInsertProcessorFunc(bean) defer handleAfterInsertProcessorFunc(bean)
_ = session.cacheInsert(tableName)
if table.Version != "" && session.statement.CheckVersion { if table.Version != "" && session.statement.CheckVersion {
verValue, err := table.VersionColumn().ValueOf(bean) verValue, err := table.VersionColumn().ValueOf(bean)
if err != nil { 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 // The in parameter bean must a struct or a point to struct. The return
// parameter is inserted and error // parameter is inserted and error
// Deprecated: Please use Insert directly // Deprecated: Please use Insert directly
func (session *Session) InsertOne(bean interface{}) (int64, error) { func (session *Session) InsertOne(bean any) (int64, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
@ -433,24 +430,11 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
return session.insertStruct(bean) 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 // 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 table := session.statement.RefTable
colNames := make([]string, 0, len(table.ColumnsSeq())) 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() { for _, col := range table.Columns() {
if col.MapType == schemas.ONLYFROMDB { if col.MapType == schemas.ONLYFROMDB {
@ -507,7 +491,7 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac
args = append(args, val) args = append(args, val)
colName := col.Name colName := col.Name
session.afterClosures = append(session.afterClosures, func(bean interface{}) { session.afterClosures = append(session.afterClosures, func(bean any) {
col := table.GetColumn(colName) col := table.GetColumn(colName)
setColumnTime(bean, col, t) setColumnTime(bean, col, t)
}) })
@ -526,7 +510,7 @@ func (session *Session) genInsertColumns(bean interface{}) ([]string, []interfac
return colNames, args, nil 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 { if len(m) == 0 {
return 0, ErrParamsType return 0, ErrParamsType
} }
@ -545,7 +529,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err
} }
sort.Strings(columns) sort.Strings(columns)
args := make([]interface{}, 0, len(m)) args := make([]any, 0, len(m))
for _, colName := range columns { for _, colName := range columns {
args = append(args, m[colName]) args = append(args, m[colName])
} }
@ -553,7 +537,7 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err
return session.insertMap(columns, args) 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 { if len(maps) == 0 {
return 0, ErrNoElementsOnSlice return 0, ErrNoElementsOnSlice
} }
@ -572,9 +556,9 @@ func (session *Session) insertMultipleMapInterface(maps []map[string]interface{}
} }
sort.Strings(columns) sort.Strings(columns)
argss := make([][]interface{}, 0, len(maps)) argss := make([][]any, 0, len(maps))
for _, m := range maps { for _, m := range maps {
args := make([]interface{}, 0, len(m)) args := make([]any, 0, len(m))
for _, colName := range columns { for _, colName := range columns {
args = append(args, m[colName]) args = append(args, m[colName])
} }
@ -604,7 +588,7 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) {
sort.Strings(columns) sort.Strings(columns)
args := make([]interface{}, 0, len(m)) args := make([]any, 0, len(m))
for _, colName := range columns { for _, colName := range columns {
args = append(args, m[colName]) args = append(args, m[colName])
} }
@ -631,9 +615,9 @@ func (session *Session) insertMultipleMapString(maps []map[string]string) (int64
} }
sort.Strings(columns) sort.Strings(columns)
argss := make([][]interface{}, 0, len(maps)) argss := make([][]any, 0, len(maps))
for _, m := range maps { for _, m := range maps {
args := make([]interface{}, 0, len(m)) args := make([]any, 0, len(m))
for _, colName := range columns { for _, colName := range columns {
args = append(args, m[colName]) args = append(args, m[colName])
} }
@ -643,7 +627,7 @@ func (session *Session) insertMultipleMapString(maps []map[string]string) (int64
return session.insertMultipleMap(columns, argss) 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() tableName := session.statement.TableName()
if len(tableName) == 0 { if len(tableName) == 0 {
return 0, ErrTableNotFound return 0, ErrTableNotFound
@ -655,10 +639,6 @@ func (session *Session) insertMap(columns []string, args []interface{}) (int64,
} }
sql = session.engine.dialect.Quoter().Replace(sql) sql = session.engine.dialect.Quoter().Replace(sql)
if err := session.cacheInsert(tableName); err != nil {
return 0, err
}
res, err := session.exec(sql, args...) res, err := session.exec(sql, args...)
if err != nil { if err != nil {
return 0, err return 0, err
@ -670,7 +650,7 @@ func (session *Session) insertMap(columns []string, args []interface{}) (int64,
return affected, nil 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() tableName := session.statement.TableName()
if len(tableName) == 0 { if len(tableName) == 0 {
return 0, ErrTableNotFound return 0, ErrTableNotFound
@ -682,10 +662,6 @@ func (session *Session) insertMultipleMap(columns []string, argss [][]interface{
} }
sql = session.engine.dialect.Quoter().Replace(sql) sql = session.engine.dialect.Quoter().Replace(sql)
if err := session.cacheInsert(tableName); err != nil {
return 0, err
}
res, err := session.exec(sql, args...) res, err := session.exec(sql, args...)
if err != nil { if err != nil {
return 0, err return 0, err

View File

@ -10,12 +10,11 @@ import (
"reflect" "reflect"
"time" "time"
"xorm.io/xorm/caches" "xorm.io/xorm/v2/contexts"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/log"
"xorm.io/xorm/log" "xorm.io/xorm/v2/names"
"xorm.io/xorm/names" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/schemas"
) )
// Interface defines the interface which Engine, EngineGroup and Session will implementate. // Interface defines the interface which Engine, EngineGroup and Session will implementate.
@ -25,89 +24,83 @@ type Interface interface {
Asc(colNames ...string) *Session Asc(colNames ...string) *Session
BufferSize(size int) *Session BufferSize(size int) *Session
Cols(columns ...string) *Session Cols(columns ...string) *Session
Count(...interface{}) (int64, error) Count(...any) (int64, error)
CreateIndexes(bean interface{}) error CreateIndexes(bean any) error
CreateUniques(bean interface{}) error CreateUniques(bean any) error
Decr(column string, arg ...interface{}) *Session Decr(column string, arg ...any) *Session
Desc(...string) *Session Desc(...string) *Session
Delete(...interface{}) (int64, error) Delete(...any) (int64, error)
Truncate(...interface{}) (int64, error) Truncate(...any) (int64, error)
Distinct(columns ...string) *Session Distinct(columns ...string) *Session
DropIndexes(bean interface{}) error DropIndexes(bean any) error
Exec(sqlOrArgs ...interface{}) (sql.Result, error) Exec(sqlOrArgs ...any) (sql.Result, error)
Exist(bean ...interface{}) (bool, error) Exist(bean ...any) (bool, error)
Find(interface{}, ...interface{}) error Find(any, ...any) error
FindAndCount(interface{}, ...interface{}) (int64, error) FindAndCount(any, ...any) (int64, error)
Get(...interface{}) (bool, error) Get(...any) (bool, error)
GroupBy(keys string) *Session GroupBy(keys string) *Session
ID(interface{}) *Session ID(any) *Session
In(string, ...interface{}) *Session In(string, ...any) *Session
Incr(column string, arg ...interface{}) *Session Incr(column string, arg ...any) *Session
Insert(...interface{}) (int64, error) Insert(...any) (int64, error)
InsertOne(interface{}) (int64, error) InsertOne(any) (int64, error)
IsTableEmpty(bean interface{}) (bool, error) IsTableEmpty(bean any) (bool, error)
IsTableExist(beanOrTableName interface{}) (bool, error) IsTableExist(beanOrTableName any) (bool, error)
Iterate(interface{}, IterFunc) error Iterate(any, IterFunc) error
Limit(int, ...int) *Session Limit(int, ...int) *Session
MustCols(columns ...string) *Session MustCols(columns ...string) *Session
NoAutoCondition(...bool) *Session NoAutoCondition(...bool) *Session
NotIn(string, ...interface{}) *Session NotIn(string, ...any) *Session
Nullable(...string) *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 Omit(columns ...string) *Session
OrderBy(order interface{}, args ...interface{}) *Session OrderBy(order any, args ...any) *Session
Ping() error Ping() error
Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error) Query(sqlOrArgs ...any) (resultsSlice []map[string][]byte, err error)
QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) QueryInterface(sqlOrArgs ...any) ([]map[string]any, error)
QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) QueryString(sqlOrArgs ...any) ([]map[string]string, error)
Rows(bean interface{}) (*Rows, error) Rows(bean any) (*Rows, error)
SetExpr(string, interface{}) *Session SetExpr(string, any) *Session
Select(string) *Session Select(string) *Session
SQL(interface{}, ...interface{}) *Session SQL(any, ...any) *Session
Sum(bean interface{}, colName string) (float64, error) Sum(bean any, colName string) (float64, error)
SumInt(bean interface{}, colName string) (int64, error) SumInt(bean any, colName string) (int64, error)
Sums(bean interface{}, colNames ...string) ([]float64, error) Sums(bean any, colNames ...string) ([]float64, error)
SumsInt(bean interface{}, colNames ...string) ([]int64, error) SumsInt(bean any, colNames ...string) ([]int64, error)
Table(tableNameOrBean interface{}) *Session Table(tableNameOrBean any) *Session
Unscoped() *Session Unscoped() *Session
Update(bean interface{}, condiBeans ...interface{}) (int64, error) Update(bean any, condiBeans ...any) (int64, error)
UseBool(...string) *Session UseBool(...string) *Session
Where(interface{}, ...interface{}) *Session Where(any, ...any) *Session
} }
// EngineInterface defines the interface which Engine, EngineGroup will implementate. // EngineInterface defines the interface which Engine, EngineGroup will implementate.
type EngineInterface interface { type EngineInterface interface {
Interface Interface
Before(func(interface{})) *Session Before(func(any)) *Session
Charset(charset string) *Session Charset(charset string) *Session
ClearCache(...interface{}) error
Context(context.Context) *Session Context(context.Context) *Session
CreateTables(...interface{}) error CreateTables(...any) error
DBMetas() ([]*schemas.Table, error) DBMetas() ([]*schemas.Table, error)
DBVersion() (*schemas.Version, error) DBVersion() (*schemas.Version, error)
Dialect() dialects.Dialect Dialect() dialects.Dialect
DriverName() string DriverName() string
DropTables(...interface{}) error DropTables(...any) error
DumpAllToFile(fp string, tp ...schemas.DBType) error DumpAllToFile(fp string, tp ...schemas.DBType) error
GetCacher(string) caches.Cacher
GetColumnMapper() names.Mapper GetColumnMapper() names.Mapper
GetDefaultCacher() caches.Cacher
GetTableMapper() names.Mapper GetTableMapper() names.Mapper
GetTZDatabase() *time.Location GetTZDatabase() *time.Location
GetTZLocation() *time.Location GetTZLocation() *time.Location
ImportFile(fp string) ([]sql.Result, error) ImportFile(fp string) ([]sql.Result, error)
MapCacher(interface{}, caches.Cacher) error
NewSession() *Session NewSession() *Session
NoAutoTime() *Session NoAutoTime() *Session
Prepare() *Session Prepare() *Session
Quote(string) string Quote(string) string
SetCacher(string, caches.Cacher)
SetConnMaxLifetime(time.Duration) SetConnMaxLifetime(time.Duration)
SetColumnMapper(names.Mapper) SetColumnMapper(names.Mapper)
SetTagIdentifier(string) SetTagIdentifier(string)
SetDefaultCacher(caches.Cacher) SetLogger(logger any)
SetLogger(logger interface{})
SetLogLevel(log.LogLevel) SetLogLevel(log.LogLevel)
SetMapper(names.Mapper) SetMapper(names.Mapper)
SetMaxOpenConns(int) SetMaxOpenConns(int)
@ -119,12 +112,12 @@ type EngineInterface interface {
SetTZLocation(tz *time.Location) SetTZLocation(tz *time.Location)
AddHook(hook contexts.Hook) AddHook(hook contexts.Hook)
ShowSQL(show ...bool) ShowSQL(show ...bool)
Sync(...interface{}) error Sync(...any) error
Sync2(...interface{}) error Sync2(...any) error
SyncWithOptions(SyncOptions, ...interface{}) (*SyncResult, error) SyncWithOptions(SyncOptions, ...any) (*SyncResult, error)
StoreEngine(storeEngine string) *Session StoreEngine(storeEngine string) *Session
TableInfo(bean interface{}) (*schemas.Table, error) TableInfo(bean any) (*schemas.Table, error)
TableName(interface{}, ...bool) string TableName(any, ...bool) string
UnMapType(reflect.Type) UnMapType(reflect.Type)
EnableSessionID(bool) EnableSessionID(bool)
} }

View File

@ -11,7 +11,7 @@ import (
) )
// AsBool convert interface as bool // AsBool convert interface as bool
func AsBool(src interface{}) (bool, error) { func AsBool(src any) (bool, error) {
switch v := src.(type) { switch v := src.(type) {
case bool: case bool:
return v, nil return v, nil

View File

@ -55,10 +55,10 @@ func cloneBytes(b []byte) []byte {
// Assign copies to dest the value in src, converting it if possible. // 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. // An error is returned if the copy would result in loss of information.
// dest should be a pointer type. // 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. // Common cases, without reflect.
switch s := src.(type) { switch s := src.(type) {
case *interface{}: case *any:
return Assign(dest, *s, originalLocation, convertedLocation) return Assign(dest, *s, originalLocation, convertedLocation)
case string: case string:
switch d := dest.(type) { switch d := dest.(type) {
@ -83,7 +83,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc
} }
*d = string(s) *d = string(s)
return nil return nil
case *interface{}: case *any:
if d == nil { if d == nil {
return ErrNilPtr return ErrNilPtr
} }
@ -110,7 +110,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc
} }
case nil: case nil:
switch d := dest.(type) { switch d := dest.(type) {
case *interface{}: case *any:
if d == nil { if d == nil {
return ErrNilPtr return ErrNilPtr
} }
@ -295,7 +295,7 @@ func Assign(dest, src interface{}, originalLocation *time.Location, convertedLoc
switch d := dest.(type) { switch d := dest.(type) {
case *string: case *string:
var sv = reflect.ValueOf(src) sv := reflect.ValueOf(src)
switch sv.Kind() { switch sv.Kind() {
case reflect.Bool, case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 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) *d = bv.(bool)
} }
return err return err
case *interface{}: case *any:
*d = src *d = src
return nil return nil
} }
@ -329,11 +329,11 @@ var (
) )
// AssignValue assign src as dv // AssignValue assign src as dv
func AssignValue(dv reflect.Value, src interface{}) error { func AssignValue(dv reflect.Value, src any) error {
if src == nil { if src == nil {
return nil return nil
} }
if v, ok := src.(*interface{}); ok { if v, ok := src.(*any); ok {
return AssignValue(dv, *v) return AssignValue(dv, *v)
} }

View File

@ -13,7 +13,7 @@ import (
) )
// AsFloat64 convets interface as float64 // AsFloat64 convets interface as float64
func AsFloat64(src interface{}) (float64, error) { func AsFloat64(src any) (float64, error) {
switch v := src.(type) { switch v := src.(type) {
case int: case int:
return float64(v), nil return float64(v), nil
@ -64,7 +64,7 @@ func AsFloat64(src interface{}) (float64, error) {
} }
// AsBigFloat converts interface as big.Float // AsBigFloat converts interface as big.Float
func AsBigFloat(src interface{}) (*big.Float, error) { func AsBigFloat(src any) (*big.Float, error) {
res := big.NewFloat(0) res := big.NewFloat(0)
switch v := src.(type) { switch v := src.(type) {
case int: case int:

View File

@ -13,7 +13,7 @@ import (
) )
// AsInt64 converts interface as int64 // AsInt64 converts interface as int64
func AsInt64(src interface{}) (int64, error) { func AsInt64(src any) (int64, error) {
switch v := src.(type) { switch v := src.(type) {
case int: case int:
return int64(v), nil return int64(v), nil
@ -112,7 +112,7 @@ func AsInt64(src interface{}) (int64, error) {
} }
// AsUint64 converts interface as uint64 // AsUint64 converts interface as uint64
func AsUint64(src interface{}) (uint64, error) { func AsUint64(src any) (uint64, error) {
switch v := src.(type) { switch v := src.(type) {
case int: case int:
return uint64(v), nil return uint64(v), nil
@ -171,7 +171,7 @@ type NullUint64 struct {
} }
// Scan implements the Scanner interface. // Scan implements the Scanner interface.
func (n *NullUint64) Scan(value interface{}) error { func (n *NullUint64) Scan(value any) error {
if value == nil { if value == nil {
n.Uint64, n.Valid = 0, false n.Uint64, n.Valid = 0, false
return nil return nil
@ -201,7 +201,7 @@ type NullUint32 struct {
} }
// Scan implements the Scanner interface. // Scan implements the Scanner interface.
func (n *NullUint32) Scan(value interface{}) error { func (n *NullUint32) Scan(value any) error {
if value == nil { if value == nil {
n.Uint32, n.Valid = 0, false n.Uint32, n.Valid = 0, false
return nil return nil

View File

@ -11,7 +11,7 @@ import (
) )
// Interface2Interface converts interface of pointer as interface of value // 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 { if v == nil {
return nil, nil return nil, nil
} }

49
internal/convert/kind.go Normal file
View File

@ -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)
}

View File

@ -6,14 +6,12 @@ package convert
import "database/sql" import "database/sql"
var ( var _ sql.Scanner = &EmptyScanner{}
_ sql.Scanner = &EmptyScanner{}
)
// EmptyScanner represents an empty scanner which will ignore the scan // EmptyScanner represents an empty scanner which will ignore the scan
type EmptyScanner struct{} type EmptyScanner struct{}
// Scan implements sql.Scanner // Scan implements sql.Scanner
func (EmptyScanner) Scan(value interface{}) error { func (EmptyScanner) Scan(value any) error {
return nil return nil
} }

View File

@ -12,7 +12,7 @@ import (
) )
// AsString converts interface as string // AsString converts interface as string
func AsString(src interface{}) string { func AsString(src any) string {
switch v := src.(type) { switch v := src.(type) {
case string: case string:
return v return v
@ -42,7 +42,7 @@ func AsString(src interface{}) string {
} }
// AsBytes converts interface as bytes // AsBytes converts interface as bytes
func AsBytes(src interface{}) ([]byte, bool) { func AsBytes(src any) ([]byte, bool) {
switch t := src.(type) { switch t := src.(type) {
case []byte: case []byte:
return t, true return t, true

View File

@ -11,7 +11,7 @@ import (
"strings" "strings"
"time" "time"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
) )
// String2Time converts a string to time with original location // String2Time converts a string to time with original location
@ -68,17 +68,13 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t
dt = dt.In(convertedLocation) dt = dt.In(convertedLocation)
return &dt, nil return &dt, nil
} else if len(s) == 8 && s[2] == ':' && s[5] == ':' { } else if len(s) == 8 && s[2] == ':' && s[5] == ':' {
currentDate := time.Now()
dt, err := time.ParseInLocation("15:04:05", s, originalLocation) dt, err := time.ParseInLocation("15:04:05", s, originalLocation)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// add current date for correct time locations
dt = dt.AddDate(currentDate.Year(), int(currentDate.Month()), currentDate.Day())
dt = dt.In(convertedLocation) dt = dt.In(convertedLocation)
// back to zero year res := time.Date(0, time.January, 1, dt.Hour(), dt.Minute(), dt.Second(), 0, convertedLocation)
dt = dt.AddDate(-currentDate.Year(), int(-currentDate.Month()), -currentDate.Day()) return &res, nil
return &dt, nil
} else { } else {
i, err := strconv.ParseInt(s, 10, 64) i, err := strconv.ParseInt(s, 10, 64)
if err == nil { if err == nil {
@ -90,7 +86,7 @@ func String2Time(s string, originalLocation *time.Location, convertedLocation *t
} }
// AsTime converts interface as time // 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) { switch t := src.(type) {
case string: case string:
return String2Time(t, dbLoc, uiLoc) return String2Time(t, dbLoc, uiLoc)

View File

@ -12,8 +12,7 @@ import (
) )
func TestString2Time(t *testing.T) { func TestString2Time(t *testing.T) {
expectedLoc, err := time.LoadLocation("Asia/Shanghai") expectedLoc := time.FixedZone("CST", 8*3600)
assert.NoError(t, err)
cases := map[string]time.Time{ cases := map[string]time.Time{
"2021-08-10": time.Date(2021, 8, 10, 8, 0, 0, 0, expectedLoc), "2021-08-10": time.Date(2021, 8, 10, 8, 0, 0, 0, expectedLoc),

View File

@ -13,24 +13,22 @@ import (
"regexp" "regexp"
"sync" "sync"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/contexts"
"xorm.io/xorm/log" "xorm.io/xorm/v2/log"
"xorm.io/xorm/names" "xorm.io/xorm/v2/names"
) )
var ( // DefaultCacheSize sets the default cache size
// DefaultCacheSize sets the default cache size var DefaultCacheSize = 200
DefaultCacheSize = 200
)
// MapToSlice map query and struct as sql and args // 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) vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { 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 var err error
query = re.ReplaceAllStringFunc(query, func(src string) string { query = re.ReplaceAllStringFunc(query, func(src string) string {
v := vv.Elem().MapIndex(reflect.ValueOf(src[1:])) 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 // 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) vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { 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 var err error
query = re.ReplaceAllStringFunc(query, func(src string) string { query = re.ReplaceAllStringFunc(query, func(src string) string {
fv := vv.Elem().FieldByName(src[1:]).Interface() fv := vv.Elem().FieldByName(src[1:]).Interface()
@ -69,7 +67,7 @@ func StructToSlice(query string, st interface{}) (string, []interface{}, error)
return "?" return "?"
}) })
if err != nil { if err != nil {
return "", []interface{}{}, err return "", []any{}, err
} }
return query, args, nil return query, args, nil
} }
@ -79,9 +77,7 @@ type cacheStruct struct {
idx int idx int
} }
var ( var _ QueryExecuter = &DB{}
_ QueryExecuter = &DB{}
)
// DB is a wrap of sql.DB with extra contents // DB is a wrap of sql.DB with extra contents
type DB struct { type DB struct {
@ -142,7 +138,7 @@ func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
} }
// QueryContext overwrites sql.DB.QueryContext // 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) hookCtx := contexts.NewContextHook(ctx, query, args)
ctx, err := db.beforeProcess(hookCtx) ctx, err := db.beforeProcess(hookCtx)
if err != nil { if err != nil {
@ -160,12 +156,12 @@ func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{
} }
// Query overwrites sql.DB.Query // 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...) return db.QueryContext(context.Background(), query, args...)
} }
// QueryMapContext executes query with parameters via map and context // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err 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 // 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) return db.QueryMapContext(context.Background(), query, mp)
} }
// QueryStructContext query rows with struct // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return nil, err return nil, err
@ -188,12 +184,12 @@ func (db *DB) QueryStructContext(ctx context.Context, query string, st interface
} }
// QueryStruct query rows with struct // 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) return db.QueryStructContext(context.Background(), query, st)
} }
// QueryRowContext query row with args // 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...) rows, err := db.QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
@ -202,12 +198,12 @@ func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interfa
} }
// QueryRow query row with args // 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...) return db.QueryRowContext(context.Background(), query, args...)
} }
// QueryRowMapContext query row with map // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
@ -216,12 +212,12 @@ func (db *DB) QueryRowMapContext(ctx context.Context, query string, mp interface
} }
// QueryRowMap query row with map // 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) return db.QueryRowMapContext(context.Background(), query, mp)
} }
// QueryRowStructContext query row with struct // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return &Row{nil, err} return &Row{nil, err}
@ -230,18 +226,16 @@ func (db *DB) QueryRowStructContext(ctx context.Context, query string, st interf
} }
// QueryRowStruct query row with struct // 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) return db.QueryRowStructContext(context.Background(), query, st)
} }
var ( var re = regexp.MustCompile(`[?](\w+)`)
re = regexp.MustCompile(`[?](\w+)`)
)
// ExecMapContext exec map with context.ContextHook // ExecMapContext exec map with context.ContextHook
// insert into (name) values (?) // insert into (name) values (?)
// insert into (name) values (?name) // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err return nil, err
@ -250,12 +244,12 @@ func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{})
} }
// ExecMap exec query with map // 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) return db.ExecMapContext(context.Background(), query, mp)
} }
// ExecStructContext exec query with map // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return nil, err return nil, err
@ -264,7 +258,7 @@ func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{
} }
// ExecContext exec query with args // 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) hookCtx := contexts.NewContextHook(ctx, query, args)
ctx, err := db.beforeProcess(hookCtx) ctx, err := db.beforeProcess(hookCtx)
if err != nil { if err != nil {
@ -279,7 +273,7 @@ func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}
} }
// ExecStruct exec query with struct // 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) return db.ExecStructContext(context.Background(), query, st)
} }

View File

@ -11,7 +11,7 @@ import (
"testing" "testing"
"time" "time"
"xorm.io/xorm/names" "xorm.io/xorm/v2/names"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
@ -239,7 +239,7 @@ func BenchmarkSliceInterfaceQuery(b *testing.B) {
} }
for rows.Next() { for rows.Next() {
slice := make([]interface{}, len(cols)) slice := make([]any, len(cols))
err = rows.ScanSlice(&slice) err = rows.ScanSlice(&slice)
if err != nil { if err != nil {
b.Error(err) b.Error(err)
@ -394,7 +394,7 @@ func BenchmarkMapInterfaceQuery(b *testing.B) {
} }
for rows.Next() { for rows.Next() {
m := make(map[string]interface{}) m := make(map[string]any)
err = rows.ScanMap(&m) err = rows.ScanMap(&m)
if err != nil { if err != nil {
b.Error(err) b.Error(err)
@ -551,7 +551,7 @@ func BenchmarkExecMap(b *testing.B) {
b.StartTimer() b.StartTimer()
mp := map[string]interface{}{ mp := map[string]any{
"name": "xlw", "name": "xlw",
"title": "tester", "title": "tester",
"age": 1.2, "age": 1.2,
@ -582,7 +582,7 @@ func TestExecMap(t *testing.T) {
t.Error(err) t.Error(err)
} }
mp := map[string]interface{}{ mp := map[string]any{
"name": "xlw", "name": "xlw",
"title": "tester", "title": "tester",
"age": 1.2, "age": 1.2,
@ -625,7 +625,8 @@ func TestExecStruct(t *testing.T) {
t.Error(err) t.Error(err)
} }
user := User{Name: "xlw", user := User{
Name: "xlw",
Title: "tester", Title: "tester",
Age: 1.2, Age: 1.2,
Alias: "lunny", Alias: "lunny",
@ -670,7 +671,8 @@ func BenchmarkExecStruct(b *testing.B) {
b.StartTimer() b.StartTimer()
user := User{Name: "xlw", user := User{
Name: "xlw",
Title: "tester", Title: "tester",
Age: 1.2, Age: 1.2,
Alias: "lunny", Alias: "lunny",

View File

@ -7,12 +7,12 @@ import (
// Queryer represents an interface to query a SQL to get data from database // Queryer represents an interface to query a SQL to get data from database
type Queryer interface { 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 // Executer represents an interface to execute a SQL
type Executer interface { 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 // QueryExecuter combines the Queryer and Executer

View File

@ -24,9 +24,9 @@ func (rs *Rows) ToMapString() ([]map[string]string, error) {
return nil, err return nil, err
} }
var results = make([]map[string]string, 0, 10) results := make([]map[string]string, 0, 10)
for rs.Next() { for rs.Next() {
var record = make(map[string]string, len(cols)) record := make(map[string]string, len(cols))
err = rs.ScanMap(&record) err = rs.ScanMap(&record)
if err != nil { if err != nil {
return nil, err 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 // 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 { if len(dest) == 0 {
return errors.New("at least one struct") return errors.New("at least one struct")
} }
@ -56,9 +56,9 @@ func (rs *Rows) ScanStructByIndex(dest ...interface{}) error {
if err != nil { if err != nil {
return err return err
} }
newDest := make([]interface{}, len(cols)) newDest := make([]any, len(cols))
var i = 0 i := 0
for _, vvv := range vvvs { for _, vvv := range vvvs {
for j := 0; j < vvv.NumField(); j++ { for j := 0; j < vvv.NumField(); j++ {
newDest[i] = vvv.Field(j).Addr().Interface() 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 // 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) vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return errors.New("dest should be a struct's pointer") return errors.New("dest should be a struct's pointer")
@ -108,7 +108,7 @@ func (rs *Rows) ScanStructByName(dest interface{}) error {
return err return err
} }
newDest := make([]interface{}, len(cols)) newDest := make([]any, len(cols))
var v EmptyScanner var v EmptyScanner
for j, name := range cols { for j, name := range cols {
f := fieldByName(vv.Elem(), rs.db.Mapper.Table2Obj(name)) 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 // 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) vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Slice {
return errors.New("dest should be a slice's pointer") return errors.New("dest should be a slice's pointer")
@ -135,7 +135,7 @@ func (rs *Rows) ScanSlice(dest interface{}) error {
return err return err
} }
newDest := make([]interface{}, len(cols)) newDest := make([]any, len(cols))
for j := 0; j < len(cols); j++ { for j := 0; j < len(cols); j++ {
if j >= vvv.Len() { if j >= vvv.Len() {
@ -158,7 +158,7 @@ func (rs *Rows) ScanSlice(dest interface{}) error {
} }
// ScanMap scan data to a map's pointer // 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) vv := reflect.ValueOf(dest)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return errors.New("dest should be a map's pointer") return errors.New("dest should be a map's pointer")
@ -169,7 +169,7 @@ func (rs *Rows) ScanMap(dest interface{}) error {
return err return err
} }
newDest := make([]interface{}, len(cols)) newDest := make([]any, len(cols))
vvv := vv.Elem() vvv := vv.Elem()
for i := range cols { for i := range cols {
@ -217,7 +217,7 @@ func (row *Row) Columns() ([]string, error) {
} }
// Scan retrieves all row column values // Scan retrieves all row column values
func (row *Row) Scan(dest ...interface{}) error { func (row *Row) Scan(dest ...any) error {
if row.err != nil { if row.err != nil {
return row.err return row.err
} }
@ -244,7 +244,7 @@ func (row *Row) Scan(dest ...interface{}) error {
} }
// ScanStructByName retrieves all row column values into a struct // 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 { if row.err != nil {
return row.err return row.err
} }
@ -265,7 +265,7 @@ func (row *Row) ScanStructByName(dest interface{}) error {
} }
// ScanStructByIndex retrieves all row column values into a struct // 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 { if row.err != nil {
return row.err 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 // 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 { if row.err != nil {
return row.err return row.err
} }
@ -308,7 +308,7 @@ func (row *Row) ScanSlice(dest interface{}) error {
} }
// ScanMap scan data to a map's pointer // 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 { if row.err != nil {
return row.err return row.err
} }
@ -336,7 +336,7 @@ func (row *Row) ToMapString() (map[string]string, error) {
return nil, err return nil, err
} }
var record = make(map[string]string, len(cols)) record := make(map[string]string, len(cols))
err = row.ScanMap(&record) err = row.ScanMap(&record)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -13,12 +13,10 @@ import (
// NullTime defines a customize type NullTime // NullTime defines a customize type NullTime
type NullTime time.Time type NullTime time.Time
var ( var _ driver.Valuer = NullTime{}
_ driver.Valuer = NullTime{}
)
// Scan implements driver.Valuer // Scan implements driver.Valuer
func (ns *NullTime) Scan(value interface{}) error { func (ns *NullTime) Scan(value any) error {
if value == nil { if value == nil {
return 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 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. // Common cases, without reflect.
switch s := src.(type) { switch s := src.(type) {
case string: case string:
@ -61,10 +59,9 @@ func convertTime(dest *NullTime, src interface{}) error {
} }
// EmptyScanner represents an empty scanner // EmptyScanner represents an empty scanner
type EmptyScanner struct { type EmptyScanner struct{}
}
// Scan implements // Scan implements
func (EmptyScanner) Scan(src interface{}) error { func (EmptyScanner) Scan(src any) error {
return nil return nil
} }

View File

@ -10,7 +10,7 @@ import (
"errors" "errors"
"reflect" "reflect"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/contexts"
) )
// Stmt reprents a stmt objects // Stmt reprents a stmt objects
@ -49,13 +49,13 @@ func (db *DB) Prepare(query string) (*Stmt, error) {
} }
// ExecMapContext execute with map // 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) vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer") 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 { for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() 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 // 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) return s.ExecMapContext(context.Background(), mp)
} }
// ExecStructContext executes with struct // 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) vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer") 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 { for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface() 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 // 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) return s.ExecStructContext(context.Background(), st)
} }
// ExecContext with args // 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) hookCtx := contexts.NewContextHook(ctx, s.query, args)
ctx, err := s.db.beforeProcess(hookCtx) ctx, err := s.db.beforeProcess(hookCtx)
if err != nil { if err != nil {
@ -102,7 +102,7 @@ func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result
} }
// QueryContext query with args // 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) hookCtx := contexts.NewContextHook(ctx, s.query, args)
ctx, err := s.db.beforeProcess(hookCtx) ctx, err := s.db.beforeProcess(hookCtx)
if err != nil { if err != nil {
@ -117,18 +117,18 @@ func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, er
} }
// Query query with args // 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...) return s.QueryContext(context.Background(), args...)
} }
// QueryMapContext query with map // 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) vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return nil, errors.New("mp should be a map's pointer") 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 { for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() 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 // 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) return s.QueryMapContext(context.Background(), mp)
} }
// QueryStructContext query with struct // 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) vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return nil, errors.New("mp should be a map's pointer") 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 { for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface() 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 // 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) return s.QueryStructContext(context.Background(), st)
} }
// QueryRowContext query row with args // 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...) rows, err := s.QueryContext(ctx, args...)
return &Row{rows, err} return &Row{rows, err}
} }
// QueryRow query row with args // 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...) return s.QueryRowContext(context.Background(), args...)
} }
// QueryRowMapContext query row with map // 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) vv := reflect.ValueOf(mp)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Map {
return &Row{nil, errors.New("mp should be a map's pointer")} 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 { for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() 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 // 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) return s.QueryRowMapContext(context.Background(), mp)
} }
// QueryRowStructContext query row with struct // 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) vv := reflect.ValueOf(st)
if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct { if vv.Kind() != reflect.Ptr || vv.Elem().Kind() != reflect.Struct {
return &Row{nil, errors.New("st should be a struct's pointer")} 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 { for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface() 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 // 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) return s.QueryRowStructContext(context.Background(), st)
} }

View File

@ -8,12 +8,10 @@ import (
"context" "context"
"database/sql" "database/sql"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/contexts"
) )
var ( var _ QueryExecuter = &Tx{}
_ QueryExecuter = &Tx{}
)
// Tx represents a transaction // Tx represents a transaction
type Tx struct { type Tx struct {
@ -105,7 +103,7 @@ func (tx *Tx) Stmt(stmt *Stmt) *Stmt {
} }
// ExecMapContext executes query with args in a map // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err 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 // 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) return tx.ExecMapContext(context.Background(), query, mp)
} }
// ExecStructContext executes query with args in a struct // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return nil, err return nil, err
@ -128,7 +126,7 @@ func (tx *Tx) ExecStructContext(ctx context.Context, query string, st interface{
} }
// ExecContext executes a query with args // 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) hookCtx := contexts.NewContextHook(ctx, query, args)
ctx, err := tx.db.beforeProcess(hookCtx) ctx, err := tx.db.beforeProcess(hookCtx)
if err != nil { 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 // 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) return tx.ExecStructContext(context.Background(), query, st)
} }
// QueryContext query with args // 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) hookCtx := contexts.NewContextHook(ctx, query, args)
ctx, err := tx.db.beforeProcess(hookCtx) ctx, err := tx.db.beforeProcess(hookCtx)
if err != nil { if err != nil {
@ -166,12 +164,12 @@ func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{
} }
// Query query with args // 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...) return tx.QueryContext(context.Background(), query, args...)
} }
// QueryMapContext query with args in a map // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return nil, err 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 // 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) return tx.QueryMapContext(context.Background(), query, mp)
} }
// QueryStructContext query with args in struct // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return nil, err return nil, err
@ -194,23 +192,23 @@ func (tx *Tx) QueryStructContext(ctx context.Context, query string, st interface
} }
// QueryStruct query with args in struct // 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) return tx.QueryStructContext(context.Background(), query, st)
} }
// QueryRowContext query one row with args // 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...) rows, err := tx.QueryContext(ctx, query, args...)
return &Row{rows, err} return &Row{rows, err}
} }
// QueryRow query one row with args // 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...) return tx.QueryRowContext(context.Background(), query, args...)
} }
// QueryRowMapContext query one row with args in a map // 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) query, args, err := MapToSlice(query, mp)
if err != nil { if err != nil {
return &Row{nil, err} 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 // 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) return tx.QueryRowMapContext(context.Background(), query, mp)
} }
// QueryRowStructContext query one row with args in struct // 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) query, args, err := StructToSlice(query, st)
if err != nil { if err != nil {
return &Row{nil, err} 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 // 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) return tx.QueryRowStructContext(context.Background(), query, st)
} }

View File

@ -19,11 +19,11 @@ func init() {
type GOjson struct{} type GOjson struct{}
// Marshal implements JSONInterface // Marshal implements JSONInterface
func (GOjson) Marshal(v interface{}) ([]byte, error) { func (GOjson) Marshal(v any) ([]byte, error) {
return gojson.Marshal(v) return gojson.Marshal(v)
} }
// Unmarshal implements JSONInterface // Unmarshal implements JSONInterface
func (GOjson) Unmarshal(data []byte, v interface{}) error { func (GOjson) Unmarshal(data []byte, v any) error {
return gojson.Unmarshal(data, v) return gojson.Unmarshal(data, v)
} }

View File

@ -8,24 +8,22 @@ import "encoding/json"
// Interface represents an interface to handle json data // Interface represents an interface to handle json data
type Interface interface { type Interface interface {
Marshal(v interface{}) ([]byte, error) Marshal(v any) ([]byte, error)
Unmarshal(data []byte, v interface{}) error Unmarshal(data []byte, v any) error
} }
var ( // DefaultJSONHandler default json handler
// DefaultJSONHandler default json handler var DefaultJSONHandler Interface = StdJSON{}
DefaultJSONHandler Interface = StdJSON{}
)
// StdJSON implements JSONInterface via encoding/json // StdJSON implements JSONInterface via encoding/json
type StdJSON struct{} type StdJSON struct{}
// Marshal implements JSONInterface // Marshal implements JSONInterface
func (StdJSON) Marshal(v interface{}) ([]byte, error) { func (StdJSON) Marshal(v any) ([]byte, error) {
return json.Marshal(v) return json.Marshal(v)
} }
// Unmarshal implements JSONInterface // Unmarshal implements JSONInterface
func (StdJSON) Unmarshal(data []byte, v interface{}) error { func (StdJSON) Unmarshal(data []byte, v any) error {
return json.Unmarshal(data, v) return json.Unmarshal(data, v)
} }

View File

@ -19,11 +19,11 @@ func init() {
type JSONiter struct{} type JSONiter struct{}
// Marshal implements JSONInterface // Marshal implements JSONInterface
func (JSONiter) Marshal(v interface{}) ([]byte, error) { func (JSONiter) Marshal(v any) ([]byte, error) {
return jsoniter.Marshal(v) return jsoniter.Marshal(v)
} }
// Unmarshal implements JSONInterface // Unmarshal implements JSONInterface
func (JSONiter) Unmarshal(data []byte, v interface{}) error { func (JSONiter) Unmarshal(data []byte, v any) error {
return jsoniter.Unmarshal(data, v) return jsoniter.Unmarshal(data, v)
} }

View File

@ -6,11 +6,11 @@ package statements
import ( import (
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// WriteArg writes an arg // 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) { switch argv := arg.(type) {
case *builder.Builder: case *builder.Builder:
if _, err := w.WriteString("("); err != nil { if _, err := w.WriteString("("); err != nil {
@ -40,7 +40,7 @@ func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) er
} }
// WriteArgs writes args // 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 { for i, arg := range args {
if err := statement.WriteArg(w, arg); err != nil { if err := statement.WriteArg(w, arg); err != nil {
return err return err

View File

@ -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)
}

View File

@ -7,7 +7,7 @@ package statements
import ( import (
"strings" "strings"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
type columnMap []string type columnMap []string

View File

@ -6,7 +6,7 @@ package statements
import ( import (
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
type QuoteReplacer struct { type QuoteReplacer struct {
@ -27,17 +27,17 @@ func (statement *Statement) QuoteReplacer(w *builder.BytesWriter) *QuoteReplacer
} }
// Where add Where statement // 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...) return statement.And(query, args...)
} }
// And add Where & and statement // 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) { switch qr := query.(type) {
case string: case string:
cond := builder.Expr(qr, args...) cond := builder.Expr(qr, args...)
statement.cond = statement.cond.And(cond) statement.cond = statement.cond.And(cond)
case map[string]interface{}: case map[string]any:
cond := make(builder.Eq) cond := make(builder.Eq)
for k, v := range qr { for k, v := range qr {
cond[statement.quote(k)] = v cond[statement.quote(k)] = v
@ -58,12 +58,12 @@ func (statement *Statement) And(query interface{}, args ...interface{}) *Stateme
} }
// Or add Where & Or statement // 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) { switch qr := query.(type) {
case string: case string:
cond := builder.Expr(qr, args...) cond := builder.Expr(qr, args...)
statement.cond = statement.cond.Or(cond) statement.cond = statement.cond.Or(cond)
case map[string]interface{}: case map[string]any:
cond := make(builder.Eq) cond := make(builder.Eq)
for k, v := range qr { for k, v := range qr {
cond[statement.quote(k)] = v cond[statement.quote(k)] = v
@ -83,14 +83,14 @@ func (statement *Statement) Or(query interface{}, args ...interface{}) *Statemen
} }
// In generate "Where column IN (?) " statement // 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...) in := builder.In(statement.quote(column), args...)
statement.cond = statement.cond.And(in) statement.cond = statement.cond.And(in)
return statement return statement
} }
// NotIn generate "Where column NOT IN (?) " 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...) notIn := builder.NotIn(statement.quote(column), args...)
statement.cond = statement.cond.And(notIn) statement.cond = statement.cond.And(notIn)
return statement return statement

View File

@ -10,8 +10,8 @@ import (
"time" "time"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
func (statement *Statement) writeDeleteOrder(w *builder.BytesWriter) error { 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() tableNameNoQuote := statement.TableName()
tableName := statement.dialect.Quoter().Quote(tableNameNoQuote) tableName := statement.dialect.Quoter().Quote(tableNameNoQuote)
table := statement.RefTable table := statement.RefTable
deleteSQLWriter := builder.NewWriter()
if _, err := fmt.Fprint(deleteSQLWriter, "DELETE FROM ", tableName); err != nil { if _, err := fmt.Fprint(deleteSQLWriter, "DELETE FROM ", tableName); err != nil {
return err return err
} }

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// ErrUnsupportedExprType represents an error with unsupported express type // ErrUnsupportedExprType represents an error with unsupported express type
@ -24,7 +24,7 @@ func (err ErrUnsupportedExprType) Error() string {
// Expr represents an SQL express // Expr represents an SQL express
type Expr struct { type Expr struct {
ColName string ColName string
Arg interface{} Arg any
} }
// WriteArgs writes args to the writer // WriteArgs writes args to the writer
@ -59,14 +59,14 @@ func (expr *Expr) WriteArgs(w *builder.BytesWriter) error {
type exprParams []Expr type exprParams []Expr
func (exprs exprParams) ColNames() []string { func (exprs exprParams) ColNames() []string {
var cols = make([]string, 0, len(exprs)) cols := make([]string, 0, len(exprs))
for _, expr := range exprs { for _, expr := range exprs {
cols = append(cols, expr.ColName) cols = append(cols, expr.ColName)
} }
return cols return cols
} }
func (exprs *exprParams) Add(name string, arg interface{}) { func (exprs *exprParams) Add(name string, arg any) {
*exprs = append(*exprs, Expr{name, arg}) *exprs = append(*exprs, Expr{name, arg})
} }

View File

@ -10,8 +10,8 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schemas.Table) error { 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 // 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 ( var (
buf = builder.NewWriter() buf = builder.NewWriter()
exprs = statement.ExprColumns exprs = statement.ExprColumns
@ -177,7 +177,7 @@ func (statement *Statement) GenInsertSQL(colNames []string, args []interface{})
} }
// GenInsertMapSQL generates insert map SQL // 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 ( var (
buf = builder.NewWriter() buf = builder.NewWriter()
exprs = statement.ExprColumns exprs = statement.ExprColumns
@ -242,7 +242,7 @@ func (statement *Statement) GenInsertMapSQL(columns []string, args []interface{}
return buf.String(), buf.Args(), nil 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 ( var (
buf = builder.NewWriter() buf = builder.NewWriter()
exprs = statement.ExprColumns exprs = statement.ExprColumns

View File

@ -9,13 +9,13 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN // 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{ statement.joins = append(statement.joins, join{
op: joinOP, op: joinOP,
table: joinTable, table: joinTable,
@ -34,13 +34,7 @@ func (statement *Statement) writeJoins(w *builder.BytesWriter) error {
return nil return nil
} }
func (statement *Statement) writeJoin(buf *builder.BytesWriter, join join) error { func (statement *Statement) writeJoinTable(buf *builder.BytesWriter, join join) error {
// write join operator
if _, err := fmt.Fprint(buf, " ", join.op, " JOIN"); err != nil {
return err
}
// write join table or subquery
switch tp := join.table.(type) { switch tp := join.table.(type) {
case builder.Builder: case builder.Builder:
if _, err := fmt.Fprintf(buf, " ("); err != nil { if _, err := fmt.Fprintf(buf, " ("); err != nil {
@ -87,6 +81,19 @@ func (statement *Statement) writeJoin(buf *builder.BytesWriter, join join) error
return err return err
} }
} }
return nil
}
func (statement *Statement) writeJoin(buf *builder.BytesWriter, join join) error {
// write join operator
if _, err := fmt.Fprint(buf, " ", join.op, " JOIN"); err != nil {
return err
}
// write join table or subquery
if err := statement.writeJoinTable(buf, join); err != nil {
return err
}
// write on condition // write on condition
if _, err := fmt.Fprint(buf, " ON "); err != nil { if _, err := fmt.Fprint(buf, " ON "); err != nil {
@ -109,3 +116,14 @@ func (statement *Statement) writeJoin(buf *builder.BytesWriter, join join) error
return nil return nil
} }
func (statement *Statement) convertJoinCondition(join join) (builder.Cond, error) {
switch condTp := join.condition.(type) {
case string:
return builder.Expr(statement.ReplaceQuote(condTp), join.args...), nil
case builder.Cond:
return condTp, nil
default:
return nil, fmt.Errorf("unsupported join condition type: %v", condTp)
}
}

View File

@ -12,8 +12,8 @@ import (
) )
type orderBy struct { type orderBy struct {
orderStr interface{} orderStr any
orderArgs []interface{} orderArgs []any
direction string // ASC, DESC or "", "" means raw orderStr 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 // 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, ""} ob := orderBy{order, args, ""}
if err := ob.CheckValid(); err != nil { if err := ob.CheckValid(); err != nil {
statement.LastError = err statement.LastError = err

View File

@ -9,12 +9,13 @@ import (
"fmt" "fmt"
"xorm.io/builder" "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 { func (statement *Statement) writePagination(bw *builder.BytesWriter) error {
dbType := statement.dialect.URI().DBType dbType := statement.dialect.URI().DBType
if dbType == "mssql" || dbType == "oracle" { if dbType == schemas.MSSQL || dbType == schemas.ORACLE {
return statement.writeOffsetFetch(bw) return statement.writeOffsetFetch(bw)
} }
return statement.writeLimitOffset(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 { func (statement *Statement) writeWhereWithMssqlPagination(w *builder.BytesWriter) error {
if !statement.cond.IsValid() { if statement.cond.IsValid() {
return statement.writeMssqlPaginationCond(w) if _, err := fmt.Fprint(w, " WHERE "); err != nil {
} return err
if _, err := fmt.Fprint(w, " WHERE "); err != nil { }
return err if err := statement.cond.WriteTo(statement.QuoteReplacer(w)); err != nil {
} return err
if err := statement.cond.WriteTo(statement.QuoteReplacer(w)); err != nil { }
return err
} }
return statement.writeMssqlPaginationCond(w) return statement.writeMssqlPaginationCond(w)
} }
@ -115,15 +116,8 @@ func (statement *Statement) writeMssqlPaginationCond(w *builder.BytesWriter) err
if _, err := fmt.Fprint(subWriter, "))"); err != nil { if _, err := fmt.Fprint(subWriter, "))"); err != nil {
return err return err
} }
if err := statement.writeWhereOrAnd(w, statement.cond.IsValid()); err != nil {
if statement.cond.IsValid() { return err
if _, err := fmt.Fprint(w, " AND "); err != nil {
return err
}
} else {
if _, err := fmt.Fprint(w, " WHERE "); err != nil {
return err
}
} }
return utils.WriteBuilder(w, subWriter) return utils.WriteBuilder(w, subWriter)

View File

@ -9,7 +9,7 @@ import (
"reflect" "reflect"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( var (
@ -36,7 +36,7 @@ func IsIDConditionWithNoTableErr(err error) bool {
} }
// ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?" // 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) { switch t := id.(type) {
case *schemas.PK: case *schemas.PK:
statement.idParam = *t statement.idParam = *t
@ -91,7 +91,7 @@ func (statement *Statement) ProcessIDParam() error {
} }
for i, col := range statement.RefTable.PKColumns() { 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]}) statement.cond = statement.cond.And(builder.Eq{colName: statement.idParam[i]})
} }
return nil return nil

View File

@ -11,11 +11,11 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// GenQuerySQL generate query SQL // 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 { if len(sqlOrArgs) > 0 {
return statement.ConvertSQLOrArgs(sqlOrArgs...) return statement.ConvertSQLOrArgs(sqlOrArgs...)
} }
@ -40,7 +40,7 @@ func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []int
} }
// GenSumSQL generates sum SQL // 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 != "" { if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil return statement.GenRawSQL(), statement.RawParams, nil
} }
@ -71,7 +71,7 @@ func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (stri
} }
// GenGetSQL generates Get SQL // 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 var isStruct bool
if bean != nil { if bean != nil {
v := rValue(bean) v := rValue(bean)
@ -127,7 +127,7 @@ func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{},
} }
// GenCountSQL generates the SQL for counting // 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 != "" { if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil return statement.GenRawSQL(), statement.RawParams, nil
} }
@ -233,8 +233,8 @@ func (statement *Statement) writeForUpdate(w *builder.BytesWriter) error {
return nil return nil
} }
if statement.dialect.URI().DBType != schemas.MYSQL { if statement.dialect.URI().DBType != schemas.MYSQL && statement.dialect.URI().DBType != schemas.POSTGRES {
return errors.New("only support mysql for update") return errors.New("only support mysql and postgres for update")
} }
_, err := fmt.Fprint(w, " FOR UPDATE") _, err := fmt.Fprint(w, " FOR UPDATE")
return err return err
@ -286,12 +286,12 @@ func (statement *Statement) writeSelect(buf *builder.BytesWriter, columnStr stri
} }
// GenExistSQL generates Exist SQL // 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 != "" { if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil return statement.GenRawSQL(), statement.RawParams, nil
} }
var b interface{} var b any
if len(bean) > 0 { if len(bean) > 0 {
b = bean[0] b = bean[0]
beanValue := reflect.ValueOf(bean[0]) beanValue := reflect.ValueOf(bean[0])
@ -393,7 +393,7 @@ func (statement *Statement) genSelectColumnStr() string {
} }
// GenFindSQL generates Find SQL // 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 != "" { if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil return statement.GenRawSQL(), statement.RawParams, nil
} }

View File

@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// Select replace select // Select replace select

View File

@ -14,13 +14,13 @@ import (
"time" "time"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/contexts"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/internal/json" "xorm.io/xorm/v2/internal/json"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/tags" "xorm.io/xorm/v2/tags"
) )
var ( var (
@ -36,9 +36,9 @@ var (
type join struct { type join struct {
op string op string
table interface{} table any
condition interface{} condition any
args []interface{} args []any
} }
// Statement save all the sql info for executing SQL // Statement save all the sql info for executing SQL
@ -59,12 +59,11 @@ type Statement struct {
AltTableName string AltTableName string
tableName string tableName string
RawSQL string RawSQL string
RawParams []interface{} RawParams []any
UseCascade bool UseCascade bool
UseAutoJoin bool UseAutoJoin bool
StoreEngine string StoreEngine string
Charset string Charset string
UseCache bool
UseAutoTime bool UseAutoTime bool
NoAutoCondition bool NoAutoCondition bool
IsDistinct bool IsDistinct bool
@ -137,8 +136,7 @@ func (statement *Statement) Reset() {
statement.tableName = "" statement.tableName = ""
statement.idParam = nil statement.idParam = nil
statement.RawSQL = "" statement.RawSQL = ""
statement.RawParams = make([]interface{}, 0) statement.RawParams = make([]any, 0)
statement.UseCache = true
statement.UseAutoTime = true statement.UseAutoTime = true
statement.NoAutoCondition = false statement.NoAutoCondition = false
statement.IsDistinct = false statement.IsDistinct = false
@ -161,7 +159,7 @@ func (statement *Statement) Reset() {
} }
// SQL adds raw sql statement // 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) { switch t := query.(type) {
case (*builder.Builder): case (*builder.Builder):
var err error var err error
@ -194,12 +192,12 @@ func (statement *Statement) SetRefValue(v reflect.Value) error {
return nil return nil
} }
func rValue(bean interface{}) reflect.Value { func rValue(bean any) reflect.Value {
return reflect.Indirect(reflect.ValueOf(bean)) return reflect.Indirect(reflect.ValueOf(bean))
} }
// SetRefBean set ref bean // SetRefBean set ref bean
func (statement *Statement) SetRefBean(bean interface{}) error { func (statement *Statement) SetRefBean(bean any) error {
var err error var err error
statement.RefTable, err = statement.tagParser.ParseWithCache(rValue(bean)) statement.RefTable, err = statement.tagParser.ParseWithCache(rValue(bean))
if err != nil { if err != nil {
@ -214,7 +212,7 @@ func (statement *Statement) NeedTableName() bool {
} }
// Incr Generate "Update ... Set column = column + arg" statement // 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 { if len(arg) > 0 {
statement.IncrColumns.Add(column, arg[0]) statement.IncrColumns.Add(column, arg[0])
} else { } else {
@ -224,7 +222,7 @@ func (statement *Statement) Incr(column string, arg ...interface{}) *Statement {
} }
// Decr Generate "Update ... Set column = column - arg" 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 { if len(arg) > 0 {
statement.DecrColumns.Add(column, arg[0]) statement.DecrColumns.Add(column, arg[0])
} else { } else {
@ -234,7 +232,7 @@ func (statement *Statement) Decr(column string, arg ...interface{}) *Statement {
} }
// SetExpr Generate "Update ... Set column = {expression}" 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 { if e, ok := expression.(string); ok {
statement.ExprColumns.Add(column, statement.dialect.Quoter().Replace(e)) statement.ExprColumns.Add(column, statement.dialect.Quoter().Replace(e))
} else { } 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 // 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) v := rValue(tableNameOrBean)
t := v.Type() t := v.Type()
if t.Kind() == reflect.Struct { if t.Kind() == reflect.Struct {
@ -367,7 +365,7 @@ func (statement *Statement) GenDelIndexSQL() []string {
return sqls 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() { switch fieldType.Kind() {
case reflect.Ptr: case reflect.Ptr:
if fieldValue.IsNil() { if fieldValue.IsNil() {
@ -503,7 +501,7 @@ func (statement *Statement) asDBCond(fieldValue reflect.Value, fieldType reflect
return fieldValue.Interface(), true, nil 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, includeVersion bool, includeUpdated bool, includeNil bool,
includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool, includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
mustColumnMap map[string]bool, tableName, aliasName string, addedTableName 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 // 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, return statement.buildConds2(table, bean, includeVersion, includeUpdated, includeNil, includeAutoIncr, statement.allUseBool, statement.useAllCols,
statement.unscoped, statement.MustColumnMap, statement.TableName(), statement.TableAlias, addedTableName) statement.unscoped, statement.MustColumnMap, statement.TableName(), statement.TableAlias, addedTableName)
} }
// MergeConds merge conditions from bean and id // 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 { if !statement.NoAutoCondition && statement.RefTable != nil {
addedTableName := (len(statement.joins) > 0) addedTableName := (len(statement.joins) > 0)
autoCond, err := statement.BuildConds(statement.RefTable, bean, true, true, false, true, addedTableName) 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 // 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...) sql, args, err := statement.convertSQLOrArgs(sqlOrArgs...)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
@ -634,11 +632,11 @@ func (statement *Statement) ConvertSQLOrArgs(sqlOrArgs ...interface{}) (string,
return statement.ReplaceQuote(sql), args, nil 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) { switch sqlOrArgs[0].(type) {
case string: case string:
if len(sqlOrArgs) > 1 { if len(sqlOrArgs) > 1 {
newArgs := make([]interface{}, 0, len(sqlOrArgs)-1) newArgs := make([]any, 0, len(sqlOrArgs)-1)
for _, arg := range sqlOrArgs[1:] { for _, arg := range sqlOrArgs[1:] {
if v, ok := arg.(time.Time); ok { if v, ok := arg.(time.Time); ok {
newArgs = append(newArgs, v.In(statement.defaultTimeZone).Format("2006-01-02 15:04:05")) newArgs = append(newArgs, v.In(statement.defaultTimeZone).Format("2006-01-02 15:04:05"))

View File

@ -12,11 +12,11 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/xorm/caches"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/names" "xorm.io/xorm/v2/names"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
"xorm.io/xorm/tags" "xorm.io/xorm/v2/tags"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@ -33,7 +33,7 @@ func TestMain(m *testing.M) {
panic("unknow dialect") 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 { if tagParser == nil {
panic("tags parser is nil") panic("tags parser is nil")
} }
@ -88,7 +88,7 @@ func TestConvertSQLOrArgs(t *testing.T) {
// ID int // ID int
// del *time.Time `xorm:"deleted"` // del *time.Time `xorm:"deleted"`
// } // }
args := []interface{}{ args := []any{
"INSERT `table` (`id`, `del`) VALUES (?, ?)", 1, (*time.Time)(nil), "INSERT `table` (`id`, `del`) VALUES (?, ?)", 1, (*time.Time)(nil),
} }
// before fix, here will panic // before fix, here will panic

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
// TableName return current tableName // TableName return current tableName

View File

@ -12,11 +12,11 @@ import (
"time" "time"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/internal/json" "xorm.io/xorm/v2/internal/json"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
func (statement *Statement) ifAddColUpdate(col *schemas.Column, includeVersion, includeUpdated, includeNil, 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, func (statement *Statement) BuildUpdates(tableValue reflect.Value,
includeVersion, includeUpdated, includeNil, includeVersion, includeUpdated, includeNil,
includeAutoIncr, update bool, includeAutoIncr, update bool,
) ([]string, []interface{}, error) { ) ([]string, []any, error) {
table := statement.RefTable table := statement.RefTable
allUseBool := statement.allUseBool allUseBool := statement.allUseBool
useAllCols := statement.useAllCols useAllCols := statement.useAllCols
@ -75,7 +75,7 @@ func (statement *Statement) BuildUpdates(tableValue reflect.Value,
nullableMap := statement.NullableMap nullableMap := statement.NullableMap
colNames := make([]string, 0) colNames := make([]string, 0)
args := make([]interface{}, 0) args := make([]any, 0)
for _, col := range table.Columns() { for _, col := range table.Columns() {
ok, err := statement.ifAddColUpdate(col, includeVersion, includeUpdated, includeNil, 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 fieldValue.CanAddr() {
if structConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { if structConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
@ -341,12 +341,59 @@ func (statement *Statement) writeUpdateTableName(updateWriter *builder.BytesWrit
} }
} }
func (statement *Statement) writeUpdateFrom(updateWriter *builder.BytesWriter) error { func (statement *Statement) writeUpdateFrom(updateWriter *builder.BytesWriter) (builder.Cond, error) {
if statement.dialect.URI().DBType != schemas.MSSQL || statement.TableAlias == "" { if statement.dialect.URI().DBType == schemas.MSSQL {
return nil if _, err := fmt.Fprint(updateWriter, " FROM"); err != nil {
return nil, err
}
if _, err := fmt.Fprint(updateWriter, " ", statement.quote(statement.TableName())); err != nil {
return nil, err
}
if statement.TableAlias != "" {
if _, err := fmt.Fprint(updateWriter, " ", statement.TableAlias); err != nil {
return nil, err
}
}
} }
_, err := fmt.Fprint(updateWriter, " FROM ", statement.quote(statement.TableName()), " ", statement.TableAlias) if len(statement.joins) == 0 {
return builder.NewCond(), nil
}
if statement.dialect.URI().DBType != schemas.MSSQL {
if _, err := fmt.Fprint(updateWriter, " FROM"); err != nil {
return nil, err
}
}
cond := builder.NewCond()
for i, join := range statement.joins {
if statement.dialect.URI().DBType == schemas.MSSQL || i > 0 {
if _, err := fmt.Fprint(updateWriter, ","); err != nil {
return nil, err
}
}
if err := statement.writeJoinTable(updateWriter, join); err != nil {
return nil, err
}
joinCond, err := statement.convertJoinCondition(join)
if err != nil {
return nil, err
}
cond = cond.And(joinCond)
}
return cond, nil
}
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 return err
} }
@ -364,14 +411,8 @@ func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter,
_, err := fmt.Fprintf(updateWriter, " LIMIT %d", limitValue) _, err := fmt.Fprintf(updateWriter, " LIMIT %d", limitValue)
return err return err
case schemas.SQLITE: case schemas.SQLITE:
if cond.IsValid() { if err := statement.writeWhereOrAnd(updateWriter, cond.IsValid()); err != nil {
if _, err := fmt.Fprint(updateWriter, " AND "); err != nil { return err
return err
}
} else {
if _, err := fmt.Fprint(updateWriter, " WHERE "); err != nil {
return err
}
} }
if _, err := fmt.Fprint(updateWriter, "rowid IN (SELECT rowid FROM ", statement.quote(tableName)); err != nil { if _, err := fmt.Fprint(updateWriter, "rowid IN (SELECT rowid FROM ", statement.quote(tableName)); err != nil {
return err return err
@ -385,14 +426,8 @@ func (statement *Statement) writeUpdateLimit(updateWriter *builder.BytesWriter,
_, err := fmt.Fprintf(updateWriter, " LIMIT %d)", limitValue) _, err := fmt.Fprintf(updateWriter, " LIMIT %d)", limitValue)
return err return err
case schemas.POSTGRES: case schemas.POSTGRES:
if cond.IsValid() { if err := statement.writeWhereOrAnd(updateWriter, cond.IsValid()); err != nil {
if _, err := fmt.Fprint(updateWriter, " AND "); err != nil { return err
return err
}
} else {
if _, err := fmt.Fprint(updateWriter, " WHERE "); err != nil {
return err
}
} }
if _, err := fmt.Fprint(updateWriter, "CTID IN (SELECT CTID FROM ", statement.quote(tableName)); err != nil { if _, err := fmt.Fprint(updateWriter, "CTID IN (SELECT CTID FROM ", statement.quote(tableName)); err != nil {
return err return err
@ -427,9 +462,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) { switch t := m.(type) {
case map[string]interface{}: case map[string]any:
conds := []builder.Cond{} conds := []builder.Cond{}
for k, v := range t { for k, v := range t {
conds = append(conds, builder.Eq{k: v}) conds = append(conds, builder.Eq{k: v})
@ -477,9 +512,9 @@ func (statement *Statement) writeVersionIncrSet(w builder.Writer, v reflect.Valu
return nil 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 { for i, expr := range statement.IncrColumns {
if i > 0 || hasPreviousSet { if i > 0 || hasPreviousSets {
if _, err := fmt.Fprint(w, ", "); err != nil { if _, err := fmt.Fprint(w, ", "); err != nil {
return err return err
} }
@ -492,10 +527,10 @@ func (statement *Statement) writeIncrSets(w builder.Writer, hasPreviousSet bool)
return nil 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 update action to like "column = column - ?"
for i, expr := range statement.DecrColumns { for i, expr := range statement.DecrColumns {
if i > 0 || hasPreviousSet { if i > 0 || hasPreviousSets {
if _, err := fmt.Fprint(w, ", "); err != nil { if _, err := fmt.Fprint(w, ", "); err != nil {
return err return err
} }
@ -508,10 +543,10 @@ func (statement *Statement) writeDecrSets(w builder.Writer, hasPreviousSet bool)
return nil 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 update action to like "column = expression"
for i, expr := range statement.ExprColumns { for i, expr := range statement.ExprColumns {
if i > 0 || hasPreviousSet { if i > 0 || hasPreviousSets {
if _, err := fmt.Fprint(w, ", "); err != nil { if _, err := fmt.Fprint(w, ", "); err != nil {
return err return err
} }
@ -544,41 +579,114 @@ func (statement *Statement) writeExprSets(w *builder.BytesWriter, hasPreviousSet
return nil return nil
} }
func (statement *Statement) writeUpdateSets(w *builder.BytesWriter, v reflect.Value, colNames []string, args []interface{}) error { func (statement *Statement) writeSetColumns(colNames []string, args []any) func(w *builder.BytesWriter) error {
previousLen := w.Len() return func(w *builder.BytesWriter) error {
for i, colName := range colNames { if len(colNames) == 0 {
if i > 0 { return nil
if _, err := fmt.Fprint(w, ", "); err != nil { }
return err 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 statement.dialect.URI().DBType != schemas.SQLITE && statement.dialect.URI().DBType != schemas.POSTGRES && len(statement.joins) > 0 {
tbName := statement.TableAlias
if tbName == "" {
tbName = statement.TableName()
}
if _, err := fmt.Fprint(w, tbName, ".", colName); err != nil {
return err
}
} else {
if _, err := fmt.Fprint(w, colName); err != nil {
return err
}
} }
} }
if _, err := fmt.Fprint(w, colName); err != nil { w.Append(args...)
return err 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 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 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 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 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 return nil
} }
var ErrNoColumnsTobeUpdated = errors.New("no columns found to be updated") 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 {
switch statement.dialect.URI().DBType {
case schemas.MYSQL:
return statement.writeUpdateMySQL(updateWriter, cond, v, colNames, args)
case schemas.MSSQL:
return statement.writeUpdateMSSQL(updateWriter, cond, v, colNames, args)
default:
return statement.writeUpdateCommon(updateWriter, cond, v, colNames, args)
}
}
func (statement *Statement) writeUpdateMySQL(updateWriter *builder.BytesWriter, cond builder.Cond, v reflect.Value, colNames []string, args []any) error {
if _, err := fmt.Fprintf(updateWriter, "UPDATE"); err != nil {
return err
}
if err := statement.writeUpdateTableName(updateWriter); err != nil {
return err
}
if err := statement.writeJoins(updateWriter); err != nil {
return err
}
if err := statement.writeUpdateSets(updateWriter, v, colNames, args); err != nil {
return err
}
// write where
if err := statement.writeWhereCond(updateWriter, cond); err != nil {
return err
}
if err := statement.writeOrderBys(updateWriter); err != nil {
return err
}
return statement.writeUpdateLimit(updateWriter, cond)
}
func (statement *Statement) writeUpdateMSSQL(updateWriter *builder.BytesWriter, cond builder.Cond, v reflect.Value, colNames []string, args []any) error {
if _, err := fmt.Fprintf(updateWriter, "UPDATE"); err != nil { if _, err := fmt.Fprintf(updateWriter, "UPDATE"); err != nil {
return err return err
} }
@ -591,47 +699,56 @@ func (statement *Statement) WriteUpdate(updateWriter *builder.BytesWriter, cond
return err return err
} }
// write set if err := statement.writeUpdateSets(updateWriter, v, colNames, args); err != nil {
if _, err := fmt.Fprint(updateWriter, " SET "); err != nil { return err
}
// write from
joinConds, err := statement.writeUpdateFrom(updateWriter)
if err != nil {
return err
}
table := statement.RefTable
if statement.HasOrderBy() && table != nil && len(table.PrimaryKeys) == 1 {
} else {
// write where
if err := statement.writeWhereCond(updateWriter, cond.And(joinConds)); err != nil {
return err
}
}
return statement.writeUpdateLimit(updateWriter, cond.And(joinConds))
}
// writeUpdateCommon write update sql for non mysql && non mssql
func (statement *Statement) writeUpdateCommon(updateWriter *builder.BytesWriter, cond builder.Cond, v reflect.Value, colNames []string, args []any) error {
if _, err := fmt.Fprintf(updateWriter, "UPDATE"); err != nil {
return err
}
if err := statement.writeUpdateTop(updateWriter); err != nil {
return err
}
if err := statement.writeUpdateTableName(updateWriter); err != nil {
return err return err
} }
previousLen := updateWriter.Len()
if err := statement.writeUpdateSets(updateWriter, v, colNames, args); err != nil { if err := statement.writeUpdateSets(updateWriter, v, colNames, args); err != nil {
return err return err
} }
// if no columns to be updated, return error
if previousLen == updateWriter.Len() {
return ErrNoColumnsTobeUpdated
}
// write from // write from
if err := statement.writeUpdateFrom(updateWriter); err != nil { joinConds, err := statement.writeUpdateFrom(updateWriter)
if err != nil {
return err return err
} }
if statement.dialect.URI().DBType == schemas.MSSQL { // write where
table := statement.RefTable if err := statement.writeWhereCond(updateWriter, cond.And(joinConds)); err != nil {
if statement.HasOrderBy() && table != nil && len(table.PrimaryKeys) == 1 { return err
} else {
// write where
if err := statement.writeWhereCond(updateWriter, cond); err != nil {
return err
}
}
} else {
// write where
if err := statement.writeWhereCond(updateWriter, cond); err != nil {
return err
}
} }
if statement.dialect.URI().DBType == schemas.MYSQL { return statement.writeUpdateLimit(updateWriter, cond.And(joinConds))
if err := statement.writeOrderBys(updateWriter); err != nil {
return err
}
}
return statement.writeUpdateLimit(updateWriter, cond)
} }

View File

@ -12,10 +12,10 @@ import (
"reflect" "reflect"
"time" "time"
"xorm.io/xorm/convert" "xorm.io/xorm/v2/dialects"
"xorm.io/xorm/dialects" "xorm.io/xorm/v2/internal/convert"
"xorm.io/xorm/internal/json" "xorm.io/xorm/v2/internal/json"
"xorm.io/xorm/schemas" "xorm.io/xorm/v2/schemas"
) )
var ( var (
@ -24,7 +24,7 @@ var (
) )
// Value2Interface convert a field value of a struct to interface for putting into database // 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 fieldValue.CanAddr() {
if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok { if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
data, err := fieldConvert.ToDB() data, err := fieldConvert.ToDB()

View File

@ -12,7 +12,7 @@ import (
type BuildReader interface { type BuildReader interface {
String() string String() string
Args() []interface{} Args() []any
} }
// WriteBuilder writes writers to one // WriteBuilder writes writers to one

View File

@ -9,6 +9,6 @@ import (
) )
// ReflectValue returns value of a bean // ReflectValue returns value of a bean
func ReflectValue(bean interface{}) reflect.Value { func ReflectValue(bean any) reflect.Value {
return reflect.Indirect(reflect.ValueOf(bean)) return reflect.Indirect(reflect.ValueOf(bean))
} }

View File

@ -17,7 +17,7 @@ type Zeroable interface {
var nilTime *time.Time var nilTime *time.Time
// IsZero returns false if k is nil or has a zero value // 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 { if k == nil {
return true return true
} }

View File

@ -13,11 +13,13 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
type MyInt int type (
type ZeroStruct struct{} MyInt int
ZeroStruct struct{}
)
func TestZero(t *testing.T) { func TestZero(t *testing.T) {
var zeroValues = []interface{}{ zeroValues := []any{
int8(0), int8(0),
int16(0), int16(0),
int(0), int(0),
@ -46,7 +48,7 @@ func TestZero(t *testing.T) {
} }
func TestIsValueZero(t *testing.T) { func TestIsValueZero(t *testing.T) {
var zeroReflectValues = []reflect.Value{ zeroReflectValues := []reflect.Value{
reflect.ValueOf(int8(0)), reflect.ValueOf(int8(0)),
reflect.ValueOf(int16(0)), reflect.ValueOf(int16(0)),
reflect.ValueOf(int(0)), reflect.ValueOf(int(0)),

View File

@ -7,26 +7,32 @@ package xorm
import ( import (
"reflect" "reflect"
"xorm.io/xorm/internal/utils" "xorm.io/xorm/v2/internal/utils"
) )
// IterFunc only use by Iterate // 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 // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
// are conditions. // are conditions.
func (session *Session) Rows(bean interface{}) (*Rows, error) { func (session *Session) Rows(bean any) (*Rows, error) {
return newRows(session, bean) return newRows(session, bean)
} }
// Iterate record by record handle records from table, condiBeans's non-empty fields // Iterate record by record handle records from table, condiBeans's non-empty fields
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct // are conditions. beans could be []Struct, []*Struct, map[int64]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 { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
session.autoResetStatement = false
defer func() {
session.autoResetStatement = true
session.resetStatement()
}()
if session.statement.LastError != nil { if session.statement.LastError != nil {
return session.statement.LastError return session.statement.LastError
} }
@ -63,16 +69,16 @@ func (session *Session) BufferSize(size int) *Session {
return session return session
} }
func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error { func (session *Session) bufferIterate(bean any, fun IterFunc) error {
var bufferSize = session.statement.BufferSize bufferSize := session.statement.BufferSize
var pLimitN = session.statement.LimitN pLimitN := session.statement.LimitN
if pLimitN != nil && bufferSize > *pLimitN { if pLimitN != nil && bufferSize > *pLimitN {
bufferSize = *pLimitN bufferSize = *pLimitN
} }
var start = session.statement.Start start := session.statement.Start
v := utils.ReflectValue(bean) v := utils.ReflectValue(bean)
sliceType := reflect.SliceOf(v.Type()) sliceType := reflect.SliceOf(v.Type())
var idx = 0 idx := 0
session.autoResetStatement = false session.autoResetStatement = false
defer func() { defer func() {
session.autoResetStatement = true session.autoResetStatement = true
@ -80,7 +86,7 @@ func (session *Session) bufferIterate(bean interface{}, fun IterFunc) error {
for bufferSize > 0 { for bufferSize > 0 {
slice := reflect.New(sliceType) 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 return err
} }

View File

@ -33,14 +33,14 @@ const (
// Logger is a logger interface // Logger is a logger interface
type Logger interface { type Logger interface {
Debug(v ...interface{}) Debug(v ...any)
Debugf(format string, v ...interface{}) Debugf(format string, v ...any)
Error(v ...interface{}) Error(v ...any)
Errorf(format string, v ...interface{}) Errorf(format string, v ...any)
Info(v ...interface{}) Info(v ...any)
Infof(format string, v ...interface{}) Infof(format string, v ...any)
Warn(v ...interface{}) Warn(v ...any)
Warnf(format string, v ...interface{}) Warnf(format string, v ...any)
Level() LogLevel Level() LogLevel
SetLevel(l LogLevel) SetLevel(l LogLevel)
@ -55,28 +55,28 @@ var _ Logger = DiscardLogger{}
type DiscardLogger struct{} type DiscardLogger struct{}
// Debug empty implementation // Debug empty implementation
func (DiscardLogger) Debug(v ...interface{}) {} func (DiscardLogger) Debug(v ...any) {}
// Debugf empty implementation // Debugf empty implementation
func (DiscardLogger) Debugf(format string, v ...interface{}) {} func (DiscardLogger) Debugf(format string, v ...any) {}
// Error empty implementation // Error empty implementation
func (DiscardLogger) Error(v ...interface{}) {} func (DiscardLogger) Error(v ...any) {}
// Errorf empty implementation // Errorf empty implementation
func (DiscardLogger) Errorf(format string, v ...interface{}) {} func (DiscardLogger) Errorf(format string, v ...any) {}
// Info empty implementation // Info empty implementation
func (DiscardLogger) Info(v ...interface{}) {} func (DiscardLogger) Info(v ...any) {}
// Infof empty implementation // Infof empty implementation
func (DiscardLogger) Infof(format string, v ...interface{}) {} func (DiscardLogger) Infof(format string, v ...any) {}
// Warn empty implementation // Warn empty implementation
func (DiscardLogger) Warn(v ...interface{}) {} func (DiscardLogger) Warn(v ...any) {}
// Warnf empty implementation // Warnf empty implementation
func (DiscardLogger) Warnf(format string, v ...interface{}) {} func (DiscardLogger) Warnf(format string, v ...any) {}
// Level empty implementation // Level empty implementation
func (DiscardLogger) Level() LogLevel { func (DiscardLogger) Level() LogLevel {
@ -128,56 +128,56 @@ func NewSimpleLogger3(out io.Writer, prefix string, flag int, l LogLevel) *Simpl
} }
// Error implement ILogger // Error implement ILogger
func (s *SimpleLogger) Error(v ...interface{}) { func (s *SimpleLogger) Error(v ...any) {
if s.level <= LOG_ERR { if s.level <= LOG_ERR {
_ = s.ERR.Output(2, fmt.Sprintln(v...)) _ = s.ERR.Output(2, fmt.Sprintln(v...))
} }
} }
// Errorf implement ILogger // Errorf implement ILogger
func (s *SimpleLogger) Errorf(format string, v ...interface{}) { func (s *SimpleLogger) Errorf(format string, v ...any) {
if s.level <= LOG_ERR { if s.level <= LOG_ERR {
_ = s.ERR.Output(2, fmt.Sprintf(format, v...)) _ = s.ERR.Output(2, fmt.Sprintf(format, v...))
} }
} }
// Debug implement ILogger // Debug implement ILogger
func (s *SimpleLogger) Debug(v ...interface{}) { func (s *SimpleLogger) Debug(v ...any) {
if s.level <= LOG_DEBUG { if s.level <= LOG_DEBUG {
_ = s.DEBUG.Output(2, fmt.Sprintln(v...)) _ = s.DEBUG.Output(2, fmt.Sprintln(v...))
} }
} }
// Debugf implement ILogger // Debugf implement ILogger
func (s *SimpleLogger) Debugf(format string, v ...interface{}) { func (s *SimpleLogger) Debugf(format string, v ...any) {
if s.level <= LOG_DEBUG { if s.level <= LOG_DEBUG {
_ = s.DEBUG.Output(2, fmt.Sprintf(format, v...)) _ = s.DEBUG.Output(2, fmt.Sprintf(format, v...))
} }
} }
// Info implement ILogger // Info implement ILogger
func (s *SimpleLogger) Info(v ...interface{}) { func (s *SimpleLogger) Info(v ...any) {
if s.level <= LOG_INFO { if s.level <= LOG_INFO {
_ = s.INFO.Output(2, fmt.Sprintln(v...)) _ = s.INFO.Output(2, fmt.Sprintln(v...))
} }
} }
// Infof implement ILogger // Infof implement ILogger
func (s *SimpleLogger) Infof(format string, v ...interface{}) { func (s *SimpleLogger) Infof(format string, v ...any) {
if s.level <= LOG_INFO { if s.level <= LOG_INFO {
_ = s.INFO.Output(2, fmt.Sprintf(format, v...)) _ = s.INFO.Output(2, fmt.Sprintf(format, v...))
} }
} }
// Warn implement ILogger // Warn implement ILogger
func (s *SimpleLogger) Warn(v ...interface{}) { func (s *SimpleLogger) Warn(v ...any) {
if s.level <= LOG_WARNING { if s.level <= LOG_WARNING {
_ = s.WARN.Output(2, fmt.Sprintln(v...)) _ = s.WARN.Output(2, fmt.Sprintln(v...))
} }
} }
// Warnf implement ILogger // Warnf implement ILogger
func (s *SimpleLogger) Warnf(format string, v ...interface{}) { func (s *SimpleLogger) Warnf(format string, v ...any) {
if s.level <= LOG_WARNING { if s.level <= LOG_WARNING {
_ = s.WARN.Output(2, fmt.Sprintf(format, v...)) _ = s.WARN.Output(2, fmt.Sprintf(format, v...))
} }

View File

@ -7,7 +7,7 @@ package log
import ( import (
"fmt" "fmt"
"xorm.io/xorm/contexts" "xorm.io/xorm/v2/contexts"
) )
// LogContext represents a log context // LogContext represents a log context
@ -23,10 +23,10 @@ type SQLLogger interface {
type ContextLogger interface { type ContextLogger interface {
SQLLogger SQLLogger
Debugf(format string, v ...interface{}) Debugf(format string, v ...any)
Errorf(format string, v ...interface{}) Errorf(format string, v ...any)
Infof(format string, v ...interface{}) Infof(format string, v ...any)
Warnf(format string, v ...interface{}) Warnf(format string, v ...any)
Level() LogLevel Level() LogLevel
SetLevel(l LogLevel) SetLevel(l LogLevel)
@ -35,9 +35,7 @@ type ContextLogger interface {
IsShowSQL() bool IsShowSQL() bool
} }
var ( var _ ContextLogger = &LoggerAdapter{}
_ ContextLogger = &LoggerAdapter{}
)
// enumerate all the context keys // enumerate all the context keys
var ( var (
@ -76,22 +74,22 @@ func (l *LoggerAdapter) AfterSQL(ctx LogContext) {
} }
// Debugf implements ContextLogger // Debugf implements ContextLogger
func (l *LoggerAdapter) Debugf(format string, v ...interface{}) { func (l *LoggerAdapter) Debugf(format string, v ...any) {
l.logger.Debugf(format, v...) l.logger.Debugf(format, v...)
} }
// Errorf implements ContextLogger // Errorf implements ContextLogger
func (l *LoggerAdapter) Errorf(format string, v ...interface{}) { func (l *LoggerAdapter) Errorf(format string, v ...any) {
l.logger.Errorf(format, v...) l.logger.Errorf(format, v...)
} }
// Infof implements ContextLogger // Infof implements ContextLogger
func (l *LoggerAdapter) Infof(format string, v ...interface{}) { func (l *LoggerAdapter) Infof(format string, v ...any) {
l.logger.Infof(format, v...) l.logger.Infof(format, v...)
} }
// Warnf implements ContextLogger // Warnf implements ContextLogger
func (l *LoggerAdapter) Warnf(format string, v ...interface{}) { func (l *LoggerAdapter) Warnf(format string, v ...any) {
l.logger.Warnf(format, v...) l.logger.Warnf(format, v...)
} }

View File

@ -26,42 +26,42 @@ func NewSyslogLogger(w *syslog.Writer) *SyslogLogger {
} }
// Debug log content as Debug // Debug log content as Debug
func (s *SyslogLogger) Debug(v ...interface{}) { func (s *SyslogLogger) Debug(v ...any) {
_ = s.w.Debug(fmt.Sprint(v...)) _ = s.w.Debug(fmt.Sprint(v...))
} }
// Debugf log content as Debug and format // 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...)) _ = s.w.Debug(fmt.Sprintf(format, v...))
} }
// Error log content as Error // Error log content as Error
func (s *SyslogLogger) Error(v ...interface{}) { func (s *SyslogLogger) Error(v ...any) {
_ = s.w.Err(fmt.Sprint(v...)) _ = s.w.Err(fmt.Sprint(v...))
} }
// Errorf log content as Errorf and format // 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...)) _ = s.w.Err(fmt.Sprintf(format, v...))
} }
// Info log content as Info // Info log content as Info
func (s *SyslogLogger) Info(v ...interface{}) { func (s *SyslogLogger) Info(v ...any) {
_ = s.w.Info(fmt.Sprint(v...)) _ = s.w.Info(fmt.Sprint(v...))
} }
// Infof log content as Infof and format // 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...)) _ = s.w.Info(fmt.Sprintf(format, v...))
} }
// Warn log content as Warn // Warn log content as Warn
func (s *SyslogLogger) Warn(v ...interface{}) { func (s *SyslogLogger) Warn(v ...any) {
_ = s.w.Warning(fmt.Sprint(v...)) _ = s.w.Warning(fmt.Sprint(v...))
} }
// Warnf log content as Warnf and format // 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...)) _ = s.w.Warning(fmt.Sprintf(format, v...))
} }

View File

@ -4,7 +4,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"xorm.io/xorm" "xorm.io/xorm/v2"
) )
// MigrateFunc is the func signature for migrating. // MigrateFunc is the func signature for migrating.
@ -87,7 +87,11 @@ func (m *Migrate) Migrate() error {
return err return err
} }
if m.initSchema != nil && m.isFirstRun() { isFirstRun, err := m.isFirstRun()
if err != nil {
return err
}
if m.initSchema != nil && isFirstRun {
return m.runInitSchema() return m.runInitSchema()
} }
@ -200,11 +204,10 @@ func (m *Migrate) migrationDidRun(mig *Migration) (bool, error) {
return count > 0, err return count > 0, err
} }
func (m *Migrate) isFirstRun() bool { func (m *Migrate) isFirstRun() (bool, error) {
row := m.db.DB().QueryRow(fmt.Sprintf("SELECT COUNT(*) FROM %s", m.options.TableName))
var count int var count int
_ = row.Scan(&count) _, err := m.db.SQL(fmt.Sprintf("SELECT COUNT(*) FROM %s", m.options.TableName)).Get(&count)
return count == 0 return count == 0, err
} }
func (m *Migrate) insertMigration(id string) error { func (m *Migrate) insertMigration(id string) error {

View File

@ -8,7 +8,7 @@ import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/xorm" "xorm.io/xorm/v2"
) )
type Person struct { type Person struct {
@ -26,28 +26,26 @@ const (
dbName = "testdb.sqlite3" dbName = "testdb.sqlite3"
) )
var ( var migrations = []*Migration{
migrations = []*Migration{ {
{ ID: "201608301400",
ID: "201608301400", Migrate: func(tx *xorm.Engine) error {
Migrate: func(tx *xorm.Engine) error { return tx.Sync(&Person{})
return tx.Sync(&Person{})
},
Rollback: func(tx *xorm.Engine) error {
return tx.DropTables(&Person{})
},
}, },
{ Rollback: func(tx *xorm.Engine) error {
ID: "201608301430", return tx.DropTables(&Person{})
Migrate: func(tx *xorm.Engine) error {
return tx.Sync(&Pet{})
},
Rollback: func(tx *xorm.Engine) error {
return tx.DropTables(&Pet{})
},
}, },
} },
) {
ID: "201608301430",
Migrate: func(tx *xorm.Engine) error {
return tx.Sync(&Pet{})
},
Rollback: func(tx *xorm.Engine) error {
return tx.DropTables(&Pet{})
},
},
}
func TestMigration(t *testing.T) { func TestMigration(t *testing.T) {
_ = os.Remove(dbName) _ = os.Remove(dbName)
@ -58,7 +56,7 @@ func TestMigration(t *testing.T) {
} }
defer db.Close() defer db.Close()
if err = db.DB().Ping(); err != nil { if err = db.Ping(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -97,7 +95,7 @@ func TestInitSchema(t *testing.T) {
log.Fatal(err) log.Fatal(err)
} }
defer db.Close() defer db.Close()
if err = db.DB().Ping(); err != nil { if err = db.Ping(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -126,7 +124,7 @@ func TestMissingID(t *testing.T) {
if db != nil { if db != nil {
defer db.Close() defer db.Close()
} }
assert.NoError(t, db.DB().Ping()) assert.NoError(t, db.Ping())
migrationsMissingID := []*Migration{ migrationsMissingID := []*Migration{
{ {
@ -141,7 +139,6 @@ func TestMissingID(t *testing.T) {
} }
func tableCount(db *xorm.Engine, tableName string) (count int) { func tableCount(db *xorm.Engine, tableName string) (count int) {
row := db.DB().QueryRow(fmt.Sprintf("SELECT COUNT(*) FROM %s", tableName)) _, _ = db.SQL(fmt.Sprintf("SELECT COUNT(*) FROM %s", tableName)).Get(&count)
_ = row.Scan(&count)
return return
} }

Some files were not shown because too many files have changed in this diff Show More