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), ``)
})