diff --git a/.github/workflows/before_script.sh b/.github/workflows/before_script.sh index b0bbee27466..d9851ef497c 100644 --- a/.github/workflows/before_script.sh +++ b/.github/workflows/before_script.sh @@ -1,6 +1,36 @@ #!/usr/bin/env bash -find . -name "*.go" | xargs gofmt -w -git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gofmt check failed,please gofmt before pr." && exit 1; fi -echo "gofmt check pass." +# Install gci +echo "Installing gci..." +go install github.com/daixiang0/gci@latest + +# Check if the GCI is installed successfully +if ! command -v gci &> /dev/null +then + echo "gci could not be installed. Please check your Go setup." + exit 1 +fi + +# Use GCI to format the code +echo "Running gci to format code..." +gci write \ + --custom-order \ + --skip-generated \ + --skip-vendor \ + -s standard \ + -s blank \ + -s default \ + -s dot \ + -s "prefix(github.com/gogf/gf/v2)" \ + -s "prefix(github.com/gogf/gf/cmd)" \ + -s "prefix(github.com/gogf/gf/contrib)" \ + -s "prefix(github.com/gogf/gf/example)" \ + ./ + +# Check the code for changes +git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gci check failed, please gci before pr." && exit 1; fi +echo "gci check pass." + +# Add the local domain name to `/etc/hosts` +echo "Adding local domain to /etc/hosts..." sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts \ No newline at end of file diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index a2860760fff..a9874b66368 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -157,13 +157,9 @@ jobs: # Polaris backend server. # docker run -d --name polaris \ # -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 \ - # loads/polaris-server-standalone:1.11.2 - # - # docker run -d --name polaris \ - # -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 \ - # loads/polaris-standalone:v1.16.3 + # polarismesh/polaris-standalone:v1.17.2 polaris: - image: loads/polaris-standalone:v1.17.2 + image: polarismesh/polaris-standalone:v1.17.2 ports: - 8090:8090 - 8091:8091 diff --git a/.github/workflows/format-code-on-push.yml b/.github/workflows/format-code-on-push.yml new file mode 100644 index 00000000000..a9c4f63cc0f --- /dev/null +++ b/.github/workflows/format-code-on-push.yml @@ -0,0 +1,61 @@ +name: Format Code on Push + +on: + push + +jobs: + format-code: + strategy: + matrix: + go-version: [ 'stable' ] + name: format-code-by-gci + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Golang ${{ matrix.go-version }} + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + - name: Install gci + run: go install github.com/daixiang0/gci@latest + - name: Run gci + run: | + gci write --custom-order \ + --skip-generated \ + --skip-vendor \ + -s standard \ + -s blank \ + -s default \ + -s dot \ + -s "prefix(github.com/gogf/gf/v2)" \ + -s "prefix(github.com/gogf/gf/cmd)" \ + -s "prefix(github.com/gogf/gf/contrib)" \ + -s "prefix(github.com/gogf/gf/example)" \ + ./ + - name: Check for changes + run: | + if [[ -n "$(git status --porcelain)" ]]; then + echo "HAS_CHANGES=true" >> $GITHUB_ENV + else + echo "HAS_CHANGES=false" >> $GITHUB_ENV + fi + - name: Configure Git + run: | + if [[ "$HAS_CHANGES" == 'true' ]]; then + git config --global user.name "github-actions[bot]" + git config --global user.email "github-actions[bot]@users.noreply.github.com" + else + echo "HAS_CHANGES= $HAS_CHANGES " + fi + - name: Commit and push changes + run: | + if [[ "$HAS_CHANGES" == 'true' ]]; then + git add . + git commit -m "Apply gci import order changes" + git push origin ${{ github.event.pull_request.head.ref }} + else + echo "No change to commit push" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 9be6b9564d8..d15a8086986 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -4,7 +4,7 @@ # If a copy of the MIT was not distributed with this file, # You can obtain one at https://github.com/gogf/gf. -name: GolangCI-Lint +name: GolangCI Lint on: push: branches: @@ -26,11 +26,11 @@ on: - feat/** jobs: - golangci: + golang-ci: strategy: matrix: go-version: [ 'stable' ] - name: golangci-lint + name: golang-ci-lint runs-on: ubuntu-latest steps: - name: Checkout @@ -39,44 +39,12 @@ jobs: uses: actions/setup-go@v5 with: go-version: ${{ matrix.go-version }} - - name: golangci-lint + - name: golang-ci-lint uses: golangci/golangci-lint-action@v6 with: # Required: specify the golangci-lint version without the patch version to always use the latest patch. version: v1.62.2 only-new-issues: true + skip-cache: true github-token: ${{ secrets.GITHUB_TOKEN }} - args: --timeout 3m0s - - name: Install gci - run: go install github.com/daixiang0/gci@latest - - name: Run gci - run: | - gci write --custom-order \ - --skip-generated \ - --skip-vendor \ - -s standard \ - -s blank \ - -s default \ - -s dot \ - -s "prefix(github.com/gogf/gf/v2)" \ - -s "prefix(github.com/gogf/gf/cmd)" \ - -s "prefix(github.com/gogf/gf/contrib)" \ - -s "prefix(github.com/gogf/gf/example)" \ - ./ - - name: Check for changes - # Check if the event is a push or a pull request from a forked repository - if: github.event_name == 'push'|| (github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == true) - run: | - if [[ -n "$(git status --porcelain)" ]]; then - echo "HAS_CHANGES=true" >> $GITHUB_ENV - else - echo "HAS_CHANGES=false" >> $GITHUB_ENV - fi - - name: Commit and push changes - if: env.HAS_CHANGES == 'true' - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git add . - git commit -m "Apply gci import order changes" - git push origin HEAD:$(git rev-parse --abbrev-ref HEAD) \ No newline at end of file + args: --timeout 3m0s --config=.golangci.yml -v diff --git a/.github/workflows/issue-check-inactive.yml b/.github/workflows/issue-check-inactive.yml index 8ca295d86ca..4b16b4f9a80 100644 --- a/.github/workflows/issue-check-inactive.yml +++ b/.github/workflows/issue-check-inactive.yml @@ -1,12 +1,12 @@ -# 规则描述:每天凌晨3点(GMT+8)执行一次,将最近7天没有活跃且非BUG的ISSUE设置标签:inactive +# Rule description: Execute the ISSUE once a day at 3 a.m. (GMT+8) and set the non-bug issue that has not been active in the last 7 days to inactive name: Issue Check Inactive on: schedule: - cron: "0 19 * * *" -env: # 设置环境变量 - TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间) +env: # Set environment variables + TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone) permissions: contents: read diff --git a/.github/workflows/issue-close-inactive.yml b/.github/workflows/issue-close-inactive.yml index 2044b4a7f4c..06272aa2132 100644 --- a/.github/workflows/issue-close-inactive.yml +++ b/.github/workflows/issue-close-inactive.yml @@ -1,12 +1,12 @@ -# 规则描述:每天凌晨 4 点 (GMT+8) 执行一次,将最近 30 天没有活跃且非 BUG 的 ISSUE 关闭 +# RULE DESCRIPTION: EXECUTED ONCE A DAY AT 4 A.M. (GMT+8) TO CLOSE NON-BUG ISSUES THAT HAVE NOT BEEN ACTIVE IN THE LAST 30 DAYS name: Issue Close Inactive on: schedule: - cron: "0 20 * * *" -env: # 设置环境变量 - TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间) +env: # Set environment variables + TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone) jobs: close-issues: diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml index 5f5e2ecdd0f..08b615380a8 100644 --- a/.github/workflows/issue-labeled.yml +++ b/.github/workflows/issue-labeled.yml @@ -1,4 +1,4 @@ -## 规则描述:当 issue 被标记为 help wanted 时,增加评论 +## Rule description: Add comments when an issue is marked as help wanted name: Issue Labeled @@ -6,8 +6,8 @@ on: issues: types: [labeled] -env: # 设置环境变量 - TZ: Asia/Shanghai # 时区(设置时区可使页面中的`最近更新时间`使用时区时间) +env: # Set environment variables + TZ: Asia/Shanghai # Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone) jobs: reply-labeled: diff --git a/.github/workflows/issue-remove-inactive.yml b/.github/workflows/issue-remove-inactive.yml index 8cd3f1ad7c0..94e975dd288 100644 --- a/.github/workflows/issue-remove-inactive.yml +++ b/.github/workflows/issue-remove-inactive.yml @@ -1,4 +1,4 @@ -# 规则描述:在 issue 没有活跃且尚未被关闭期间,若 issue 作者更新或评论该 ISSUE,则移除其 inactive 标签 +# Rule description: If an issue author updates or comments on an issue while it is not active and has not been closed, the inactive tag will be removed name: Issue Remove Inactive on: @@ -7,8 +7,8 @@ on: issue_comment: types: [created, edited] -env: # 设置环境变量 - TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间) +env: # Set environment variables + TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone) permissions: contents: read diff --git a/.github/workflows/issue-remove-need-more-details.yml b/.github/workflows/issue-remove-need-more-details.yml index e9e2ab03b83..80379693e20 100644 --- a/.github/workflows/issue-remove-need-more-details.yml +++ b/.github/workflows/issue-remove-need-more-details.yml @@ -1,4 +1,4 @@ -# 规则描述:将需要提供更多细节且暂未关闭的 issue,在 issue 作者评论后,移除 need more details 标签 +# Rule Description: For issues that need more details and are not yet closed, remove the "need more details" tag after the issue author comments name: Issue Remove Need More Details on: @@ -7,8 +7,8 @@ on: issue_comment: types: [created, edited] -env: # 设置环境变量 - TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间) +env: # Set environment variables + TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone) permissions: contents: read diff --git a/.github/workflows/nacos/docker-compose.yml b/.github/workflows/nacos/docker-compose.yml index 3e69daa7c5a..24b39e3e6d0 100644 --- a/.github/workflows/nacos/docker-compose.yml +++ b/.github/workflows/nacos/docker-compose.yml @@ -17,7 +17,7 @@ services: retries: 10 initializer: - image: loads/curl:latest + image: alpine/curl:latest depends_on: nacos: condition: service_healthy diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000000..895782dadd7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "examples"] + path = examples + url = git@github.com:gogf/examples.git diff --git a/.golangci.yml b/.golangci.yml index a2b04ea7735..f1512b2b310 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,28 +6,46 @@ # Options for analysis running. run: + # Timeout for analysis, e.g. 30s, 5m. + # Default: 1m + timeout: 5m # Exit code when at least one issue was found. # Default: 1 issues-exit-code: 2 - # Include test files or not. # Default: true tests: false - - # Which dirs to skip: issues from them won't be reported. - # Can use regexp here: `generated.*`, regexp is applied on full path. - # Default value is empty list, - # but default dirs are skipped independently of this option's value (see skip-dirs-use-default). - # "/" will be replaced by current OS file path separator to properly work on Windows. - skip-dirs: [] - - # Which files to skip: they will be analyzed, but issues from them won't be reported. - # Default value is empty list, - # but there is no need to include all autogenerated files, - # we confidently recognize autogenerated files. - # If it's not please let us know. - # "/" will be replaced by current OS file path separator to properly work on Windows. - skip-files: [] + # List of build tags, all linters use it. + # Default: [] + build-tags: [] + # If set, we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + # + # Allowed values: readonly|vendor|mod + # Default: "" + modules-download-mode: readonly + # Allow multiple parallel golangci-lint instances running. + # If false, golangci-lint acquires file lock on start. + # Default: false + allow-parallel-runners: true + # Allow multiple golangci-lint instances running, but serialize them around a lock. + # If false, golangci-lint exits with an error if it fails to acquire file lock on start. + # Default: false + allow-serial-runners: true + # Define the Go version limit. + # Mainly related to generics support since go1.18. + # Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17 + go: '1.20' + # Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously. + # If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota. + # Default: the number of logical CPUs in the machine + concurrency: 4 # Main linters configurations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..1d26a21f207 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing + +Thanks for taking the time to join our community and start contributing! + +## With issues +- Use the search tool before opening a new issue. +- Please provide source code and commit sha if you found a bug. +- Review existing issues and provide feedback or react to them. + +## With pull requests +- Open your pull request against `master` +- Your pull request should have no more than two commits, if not you should squash them. +- It should pass all tests in the available continuous integrations systems such as GitHub CI. +- You should add/modify tests to cover your proposed code changes. +- If your pull request contains a new feature, please document it on the README. diff --git a/Makefile b/Makefile index b354b5cfb93..46265203a92 100644 --- a/Makefile +++ b/Makefile @@ -27,3 +27,30 @@ version: newVersion=$(to); \ ./.set_version.sh ./ $$newVersion; \ echo "make version to=$(to) done" + + +# update submodules +.PHONY: subup +subup: + @set -e; \ + cd examples; \ + echo "Updating submodules..."; \ + git pull origin; \ + cd ..; + +# update and commit submodules +.PHONY: subsync +subsync: subup + @set -e; \ + echo "";\ + cd examples; \ + echo "Checking for changes..."; \ + if git diff-index --quiet HEAD --; then \ + echo "No changes to commit"; \ + else \ + echo "Found changes, committing..."; \ + git add -A; \ + git commit -m "examples update"; \ + git push origin; \ + fi; \ + cd ..; diff --git a/cmd/gf/go.mod b/cmd/gf/go.mod index e3cd3bd69ad..e2d19e73074 100644 --- a/cmd/gf/go.mod +++ b/cmd/gf/go.mod @@ -50,8 +50,8 @@ require ( go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect - golang.org/x/crypto v0.30.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/cmd/gf/go.sum b/cmd/gf/go.sum index 47a75885b3e..ad3b4a1875d 100644 --- a/cmd/gf/go.sum +++ b/cmd/gf/go.sum @@ -145,8 +145,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= @@ -155,8 +155,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/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.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/contrib/config/consul/go.mod b/contrib/config/consul/go.mod index 8fc085975ac..b59d1c85691 100644 --- a/contrib/config/consul/go.mod +++ b/contrib/config/consul/go.mod @@ -40,7 +40,7 @@ require ( go.opentelemetry.io/otel/sdk v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/contrib/config/consul/go.sum b/contrib/config/consul/go.sum index ad79d6148b6..79952db4141 100644 --- a/contrib/config/consul/go.sum +++ b/contrib/config/consul/go.sum @@ -218,8 +218,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/contrib/config/nacos/go.mod b/contrib/config/nacos/go.mod index 470e94613b9..beb5ce58eb1 100644 --- a/contrib/config/nacos/go.mod +++ b/contrib/config/nacos/go.mod @@ -55,8 +55,8 @@ require ( go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.30.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/contrib/config/nacos/go.sum b/contrib/config/nacos/go.sum index b8dc3341b15..4f40bf72e5d 100644 --- a/contrib/config/nacos/go.sum +++ b/contrib/config/nacos/go.sum @@ -155,8 +155,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -175,8 +175,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= diff --git a/contrib/config/polaris/go.mod b/contrib/config/polaris/go.mod index 39b5590a8c8..0d11a9bed82 100644 --- a/contrib/config/polaris/go.mod +++ b/contrib/config/polaris/go.mod @@ -50,7 +50,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect diff --git a/contrib/config/polaris/go.sum b/contrib/config/polaris/go.sum index faf2d7160fa..ebc40fcbec8 100644 --- a/contrib/config/polaris/go.sum +++ b/contrib/config/polaris/go.sum @@ -595,8 +595,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/contrib/drivers/mysql/mysql_z_unit_model_test.go b/contrib/drivers/mysql/mysql_z_unit_model_test.go index 9be10ff1313..d28f461c241 100644 --- a/contrib/drivers/mysql/mysql_z_unit_model_test.go +++ b/contrib/drivers/mysql/mysql_z_unit_model_test.go @@ -2812,6 +2812,28 @@ func Test_Model_OnDuplicate(t *testing.T) { }) } +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} + func Test_Model_OnDuplicateEx(t *testing.T) { table := createInitTable() defer dropTable(table) diff --git a/contrib/drivers/pgsql/pgsql_format_upsert.go b/contrib/drivers/pgsql/pgsql_format_upsert.go index c4c8af91122..fc003cb4ce5 100644 --- a/contrib/drivers/pgsql/pgsql_format_upsert.go +++ b/contrib/drivers/pgsql/pgsql_format_upsert.go @@ -40,6 +40,25 @@ func (d *Driver) FormatUpsert(columns []string, list gdb.List, option gdb.DoInse d.Core.QuoteWord(k), v, ) + case gdb.Counter, *gdb.Counter: + var counter gdb.Counter + switch value := v.(type) { + case gdb.Counter: + counter = value + case *gdb.Counter: + counter = *value + } + operator, columnVal := "+", counter.Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(counter.Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=EXCLUDED.%s", diff --git a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go index d7748f07f17..3a51ba264dc 100644 --- a/contrib/drivers/pgsql/pgsql_z_unit_model_test.go +++ b/contrib/drivers/pgsql/pgsql_z_unit_model_test.go @@ -521,6 +521,28 @@ func Test_Model_OnDuplicate(t *testing.T) { }) } +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} + func Test_Model_OnDuplicateEx(t *testing.T) { table := createInitTable() defer dropTable(table) diff --git a/contrib/drivers/sqlite/sqlite_format_upsert.go b/contrib/drivers/sqlite/sqlite_format_upsert.go index 5821144a13e..c80d5dfd74e 100644 --- a/contrib/drivers/sqlite/sqlite_format_upsert.go +++ b/contrib/drivers/sqlite/sqlite_format_upsert.go @@ -40,6 +40,25 @@ func (d *Driver) FormatUpsert(columns []string, list gdb.List, option gdb.DoInse d.Core.QuoteWord(k), v, ) + case gdb.Counter, *gdb.Counter: + var counter gdb.Counter + switch value := v.(type) { + case gdb.Counter: + counter = value + case *gdb.Counter: + counter = *value + } + operator, columnVal := "+", counter.Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(counter.Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=EXCLUDED.%s", diff --git a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go index 19e97bfa51a..03e8465c7fc 100644 --- a/contrib/drivers/sqlite/sqlite_z_unit_model_test.go +++ b/contrib/drivers/sqlite/sqlite_z_unit_model_test.go @@ -4324,3 +4324,25 @@ func Test_OrderRandom(t *testing.T) { t.Assert(len(result), TableSize) }) } + +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} diff --git a/contrib/drivers/sqlitecgo/sqlite_format_upsert.go b/contrib/drivers/sqlitecgo/sqlite_format_upsert.go new file mode 100644 index 00000000000..63cb33e5a06 --- /dev/null +++ b/contrib/drivers/sqlitecgo/sqlite_format_upsert.go @@ -0,0 +1,90 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package sqlitecgo + +import ( + "fmt" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" +) + +// FormatUpsert returns SQL clause of type upsert for SQLite. +// For example: ON CONFLICT (id) DO UPDATE SET ... +func (d *Driver) FormatUpsert(columns []string, list gdb.List, option gdb.DoInsertOption) (string, error) { + if len(option.OnConflict) == 0 { + return "", gerror.NewCode( + gcode.CodeMissingParameter, `Please specify conflict columns`, + ) + } + + var onDuplicateStr string + if option.OnDuplicateStr != "" { + onDuplicateStr = option.OnDuplicateStr + } else if len(option.OnDuplicateMap) > 0 { + for k, v := range option.OnDuplicateMap { + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + switch v.(type) { + case gdb.Raw, *gdb.Raw: + onDuplicateStr += fmt.Sprintf( + "%s=%s", + d.Core.QuoteWord(k), + v, + ) + case gdb.Counter, *gdb.Counter: + var counter gdb.Counter + switch value := v.(type) { + case gdb.Counter: + counter = value + case *gdb.Counter: + counter = *value + } + operator, columnVal := "+", counter.Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s%s%s", + d.QuoteWord(k), + d.QuoteWord(counter.Field), + operator, + gconv.String(columnVal), + ) + default: + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s", + d.Core.QuoteWord(k), + d.Core.QuoteWord(gconv.String(v)), + ) + } + } + } else { + for _, column := range columns { + // If it's SAVE operation, do not automatically update the creating time. + if d.Core.IsSoftCreatedFieldName(column) { + continue + } + if len(onDuplicateStr) > 0 { + onDuplicateStr += "," + } + onDuplicateStr += fmt.Sprintf( + "%s=EXCLUDED.%s", + d.Core.QuoteWord(column), + d.Core.QuoteWord(column), + ) + } + } + + conflictKeys := gstr.Join(option.OnConflict, ",") + + return fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET ", conflictKeys) + onDuplicateStr, nil +} diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go b/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go index 6c578225e53..476ae1a0e97 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_do_filter.go @@ -10,8 +10,6 @@ import ( "context" "github.com/gogf/gf/v2/database/gdb" - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/text/gstr" ) @@ -26,14 +24,6 @@ func (d *Driver) DoFilter( case gstr.HasPrefix(sql, gdb.InsertOperationReplace): sql = "INSERT OR REPLACE" + sql[len(gdb.InsertOperationReplace):] - - default: - if gstr.Contains(sql, gdb.InsertOnDuplicateKeyUpdate) { - return sql, args, gerror.NewCode( - gcode.CodeNotSupported, - `Save operation is not supported by sqlite driver`, - ) - } } return d.Core.DoFilter(ctx, link, sql, args) } diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_tables.go b/contrib/drivers/sqlitecgo/sqlitecgo_tables.go index d985c3a62af..993c6cf8bdc 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_tables.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_tables.go @@ -12,6 +12,10 @@ import ( "github.com/gogf/gf/v2/database/gdb" ) +const ( + tablesSqlTmp = `SELECT NAME FROM SQLITE_MASTER WHERE TYPE='table' ORDER BY NAME` +) + // Tables retrieves and returns the tables of current schema. // It's mainly used in cli tool chain for automatically generating the models. func (d *Driver) Tables(ctx context.Context, schema ...string) (tables []string, err error) { @@ -21,11 +25,7 @@ func (d *Driver) Tables(ctx context.Context, schema ...string) (tables []string, return nil, err } - result, err = d.DoSelect( - ctx, - link, - `SELECT NAME FROM SQLITE_MASTER WHERE TYPE='table' ORDER BY NAME`, - ) + result, err = d.DoSelect(ctx, link, tablesSqlTmp) if err != nil { return } diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_init_test.go b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_init_test.go index fe778b93f8f..0dd2aa0dc76 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_init_test.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_init_test.go @@ -11,8 +11,6 @@ import ( "github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/database/gdb" - "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gfile" @@ -27,9 +25,6 @@ var ( configNode gdb.ConfigNode dbDir = gfile.Temp("sqlite") ctx = gctx.New() - - // Error - ErrorSave = gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`) ) const ( diff --git a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go index 613ef9c64b3..3ad793df2d3 100644 --- a/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go +++ b/contrib/drivers/sqlitecgo/sqlitecgo_z_unit_model_test.go @@ -375,7 +375,7 @@ func Test_Model_Save(t *testing.T) { "nickname": "oldme", "create_time": CreateTime, }).OnConflict("id").Save() - t.Assert(err, ErrorSave) + t.AssertNil(err) }) } @@ -4361,3 +4361,25 @@ func TestResult_Structs1(t *testing.T) { t.Assert(array[1].Name, "smith") }) } + +func Test_Model_OnDuplicateWithCounter(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + data := g.Map{ + "id": 1, + "passport": "pp1", + "password": "pw1", + "nickname": "n1", + "create_time": "2016-06-06", + } + _, err := db.Model(table).OnConflict("id").OnDuplicate(g.Map{ + "id": gdb.Counter{Field: "id", Value: 999999}, + }).Data(data).Save() + t.AssertNil(err) + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNil(one) + }) +} diff --git a/contrib/registry/nacos/go.mod b/contrib/registry/nacos/go.mod index ec29dd1befd..768b3aa447b 100644 --- a/contrib/registry/nacos/go.mod +++ b/contrib/registry/nacos/go.mod @@ -54,8 +54,8 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.30.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sync v0.10.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect diff --git a/contrib/registry/nacos/go.sum b/contrib/registry/nacos/go.sum index 31eb4b325ec..e2e0523728e 100644 --- a/contrib/registry/nacos/go.sum +++ b/contrib/registry/nacos/go.sum @@ -133,8 +133,8 @@ go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY= -golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -143,8 +143,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= diff --git a/contrib/registry/polaris/go.mod b/contrib/registry/polaris/go.mod index 883be167dea..cc7ac6c19d7 100644 --- a/contrib/registry/polaris/go.mod +++ b/contrib/registry/polaris/go.mod @@ -50,7 +50,7 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect diff --git a/contrib/registry/polaris/go.sum b/contrib/registry/polaris/go.sum index faf2d7160fa..ebc40fcbec8 100644 --- a/contrib/registry/polaris/go.sum +++ b/contrib/registry/polaris/go.sum @@ -595,8 +595,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/contrib/trace/otlpgrpc/go.mod b/contrib/trace/otlpgrpc/go.mod index 6f9aeee21e4..7e77a80f1d0 100644 --- a/contrib/trace/otlpgrpc/go.mod +++ b/contrib/trace/otlpgrpc/go.mod @@ -35,7 +35,7 @@ require ( go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect diff --git a/contrib/trace/otlpgrpc/go.sum b/contrib/trace/otlpgrpc/go.sum index c5557eb6c89..0389dfd54c5 100644 --- a/contrib/trace/otlpgrpc/go.sum +++ b/contrib/trace/otlpgrpc/go.sum @@ -68,8 +68,8 @@ go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxi go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= diff --git a/contrib/trace/otlphttp/go.mod b/contrib/trace/otlphttp/go.mod index d7d6125b997..6d7038d4f60 100644 --- a/contrib/trace/otlphttp/go.mod +++ b/contrib/trace/otlphttp/go.mod @@ -34,7 +34,7 @@ require ( go.opentelemetry.io/otel/metric v1.32.0 // indirect go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - golang.org/x/net v0.32.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.21.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect diff --git a/contrib/trace/otlphttp/go.sum b/contrib/trace/otlphttp/go.sum index a5ac0d2a22f..562af204796 100644 --- a/contrib/trace/otlphttp/go.sum +++ b/contrib/trace/otlphttp/go.sum @@ -66,8 +66,8 @@ go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQD go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= -golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 50971611258..f4faa0bf4f9 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -583,24 +583,8 @@ func (c *Core) DoUpdate(ctx context.Context, link Link, table string, data inter switch kind { case reflect.Map, reflect.Struct: var ( - fields []string - dataMap map[string]interface{} - counterHandler = func(column string, counter Counter) { - if counter.Value != 0 { - column = c.QuoteWord(column) - var ( - columnRef = c.QuoteWord(counter.Field) - columnVal = counter.Value - operator = "+" - ) - if columnVal < 0 { - operator = "-" - columnVal = -columnVal - } - fields = append(fields, fmt.Sprintf("%s=%s%s?", column, columnRef, operator)) - params = append(params, columnVal) - } - } + fields []string + dataMap map[string]interface{} ) dataMap, err = c.ConvertDataForRecord(ctx, data, table) if err != nil { @@ -620,13 +604,21 @@ func (c *Core) DoUpdate(ctx context.Context, link Link, table string, data inter } for _, k := range keysInSequence { v := dataMap[k] - switch value := v.(type) { - case *Counter: - counterHandler(k, *value) - - case Counter: - counterHandler(k, value) - + switch v.(type) { + case Counter, *Counter: + var counter Counter + switch value := v.(type) { + case Counter: + counter = value + case *Counter: + counter = *value + } + if counter.Value == 0 { + continue + } + operator, columnVal := c.getCounterAlter(counter) + fields = append(fields, fmt.Sprintf("%s=%s%s?", c.QuoteWord(k), c.QuoteWord(counter.Field), operator)) + params = append(params, columnVal) default: if s, ok := v.(Raw); ok { fields = append(fields, c.QuoteWord(k)+"="+gconv.String(s)) @@ -796,3 +788,12 @@ func (c *Core) IsSoftCreatedFieldName(fieldName string) bool { func (c *Core) FormatSqlBeforeExecuting(sql string, args []interface{}) (newSql string, newArgs []interface{}) { return handleSliceAndStructArgsForSql(sql, args) } + +// getCounterAlter +func (c *Core) getCounterAlter(counter Counter) (operator string, columnVal float64) { + operator, columnVal = "+", counter.Value + if columnVal < 0 { + operator, columnVal = "-", -columnVal + } + return +} diff --git a/database/gdb/gdb_core_underlying.go b/database/gdb/gdb_core_underlying.go index 045d11c65af..25c60a4baf7 100644 --- a/database/gdb/gdb_core_underlying.go +++ b/database/gdb/gdb_core_underlying.go @@ -388,6 +388,22 @@ func (c *Core) FormatUpsert(columns []string, list List, option DoInsertOption) c.QuoteWord(k), v, ) + case Counter, *Counter: + var counter Counter + switch value := v.(type) { + case Counter: + counter = value + case *Counter: + counter = *value + } + operator, columnVal := c.getCounterAlter(counter) + onDuplicateStr += fmt.Sprintf( + "%s=%s%s%s", + c.QuoteWord(k), + c.QuoteWord(counter.Field), + operator, + gconv.String(columnVal), + ) default: onDuplicateStr += fmt.Sprintf( "%s=VALUES(%s)", diff --git a/example/README.MD b/example/README.MD new file mode 100644 index 00000000000..d517ff61851 --- /dev/null +++ b/example/README.MD @@ -0,0 +1,2 @@ +This repository is deprecated and moved to standalone +repository: https://github.com/gogf/examples \ No newline at end of file diff --git a/examples b/examples index 155fc508056..9fcc5237e9e 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 155fc50805680de363458cc6726f8617b3206318 +Subproject commit 9fcc5237e9e16039cec66225c64d4576cdc5c0cc diff --git a/util/gpage/gpage.go b/util/gpage/gpage.go index ac138d60f78..d434e3f638f 100644 --- a/util/gpage/gpage.go +++ b/util/gpage/gpage.go @@ -164,7 +164,7 @@ func (p *Page) GetContent(mode int) string { p.FirstPageTag = "首页" p.LastPageTag = "尾页" return fmt.Sprintf( - `%s%s[第%d页]%s%s第%s页`, + `%s%s[第 %d 页]%s%s第%s页`, p.FirstPage(), p.PrevPage(), p.CurrentPage, @@ -184,7 +184,7 @@ func (p *Page) GetContent(mode int) string { pageStr += p.NextPage() pageStr += p.LastPage() pageStr += fmt.Sprintf( - `当前页%d/%d 共%d条`, + `当前页 %d/%d 共 %d 条`, p.CurrentPage, p.TotalPage, p.TotalSize, @@ -210,20 +210,24 @@ func (p *Page) GetContent(mode int) string { // The UrlTemplate attribute can be a URL or URI string containing the "{.page}" placeholder, // which will be replaced by the actual page number. func (p *Page) GetUrl(page int) string { - return gstr.Replace(p.UrlTemplate, DefaultPagePlaceHolder, gconv.String(page)) + return html.EscapeString(gstr.Replace(p.UrlTemplate, DefaultPagePlaceHolder, gconv.String(page))) } // GetLink returns the HTML link tag `a` content for given page number. func (p *Page) GetLink(page int, text, title string) string { + var ( + escapedTitle = html.EscapeString(title) + escapedText = html.EscapeString(text) + ) if len(p.AjaxActionName) > 0 { return fmt.Sprintf( `%s`, - p.LinkStyle, p.AjaxActionName, p.GetUrl(page), html.EscapeString(title), text, + p.LinkStyle, p.AjaxActionName, p.GetUrl(page), escapedTitle, escapedText, ) } else { return fmt.Sprintf( `%s`, - p.LinkStyle, p.GetUrl(page), html.EscapeString(title), text, + p.LinkStyle, p.GetUrl(page), escapedTitle, escapedText, ) } } diff --git a/util/gpage/gpage_z_unit_test.go b/util/gpage/gpage_z_unit_test.go index 79881330533..5399db86fdb 100644 --- a/util/gpage/gpage_z_unit_test.go +++ b/util/gpage/gpage_z_unit_test.go @@ -33,27 +33,27 @@ func Test_New(t *testing.T) { func Test_Basic(t *testing.T) { gtest.C(t, func(t *gtest.T) { page := gpage.New(9, 2, 1, `/user/list?page={.page}`) - t.Assert(page.NextPage(), `>`) + t.Assert(page.NextPage(), `>`) t.Assert(page.PrevPage(), `<`) t.Assert(page.FirstPage(), `|<`) - t.Assert(page.LastPage(), `>|`) + t.Assert(page.LastPage(), `>|`) t.Assert(page.PageBar(), `12345`) }) gtest.C(t, func(t *gtest.T) { page := gpage.New(9, 2, 3, `/user/list?page={.page}`) - t.Assert(page.NextPage(), `>`) - t.Assert(page.PrevPage(), `<`) - t.Assert(page.FirstPage(), `|<`) - t.Assert(page.LastPage(), `>|`) + t.Assert(page.NextPage(), `>`) + t.Assert(page.PrevPage(), `<`) + t.Assert(page.FirstPage(), `|<`) + t.Assert(page.LastPage(), `>|`) t.Assert(page.PageBar(), `12345`) }) gtest.C(t, func(t *gtest.T) { page := gpage.New(9, 2, 5, `/user/list?page={.page}`) t.Assert(page.NextPage(), `>`) - t.Assert(page.PrevPage(), `<`) - t.Assert(page.FirstPage(), `|<`) + t.Assert(page.PrevPage(), `<`) + t.Assert(page.FirstPage(), `|<`) t.Assert(page.LastPage(), `>|`) t.Assert(page.PageBar(), `12345`) }) @@ -82,10 +82,10 @@ func Test_CustomStyle(t *testing.T) { page.LinkStyle = "MyPageLink" page.SpanStyle = "MyPageSpan" page.SelectStyle = "MyPageSelect" - t.Assert(page.NextPage(), `>`) - t.Assert(page.PrevPage(), `<`) - t.Assert(page.FirstPage(), `|<`) - t.Assert(page.LastPage(), `>|`) + t.Assert(page.NextPage(), `>`) + t.Assert(page.PrevPage(), `<`) + t.Assert(page.FirstPage(), `|<`) + t.Assert(page.LastPage(), `>|`) t.Assert(page.PageBar(), `12345`) t.Assert(page.SelectBar(), ``) }) @@ -95,10 +95,10 @@ func Test_Ajax(t *testing.T) { gtest.C(t, func(t *gtest.T) { page := gpage.New(5, 1, 2, `/user/list/{.page}`) page.AjaxActionName = "LoadPage" - t.Assert(page.NextPage(), `>`) - t.Assert(page.PrevPage(), `<`) - t.Assert(page.FirstPage(), `|<`) - t.Assert(page.LastPage(), `>|`) + t.Assert(page.NextPage(), `>`) + t.Assert(page.PrevPage(), `<`) + t.Assert(page.FirstPage(), `|<`) + t.Assert(page.LastPage(), `>|`) t.Assert(page.PageBar(), `12345`) }) } @@ -108,8 +108,8 @@ func Test_PredefinedContent(t *testing.T) { page := gpage.New(5, 1, 2, `/user/list/{.page}`) page.AjaxActionName = "LoadPage" t.Assert(page.GetContent(1), `上一页 2 下一页`) - t.Assert(page.GetContent(2), `首页<<上一页[第2页]下一页>>尾页页`) - t.Assert(page.GetContent(3), `首页上一页12345下一页尾页当前页2/5 共5条`) + t.Assert(page.GetContent(2), `首页<<上一页[第 2 页]下一页>>尾页页`) + t.Assert(page.GetContent(3), `首页上一页12345下一页尾页当前页 2/5 共 5 条`) t.Assert(page.GetContent(4), `首页上一页12345下一页尾页`) t.Assert(page.GetContent(5), ``) })