Compare commits

...

96 Commits

Author SHA1 Message Date
1ede8c77ba version updates 2022-06-24 15:21:36 +08:00
48f95d0009 fix issue in Response.WriteJson/Xml functions 2022-06-24 15:21:10 +08:00
0bb57b8989 go.sum update 2022-06-24 15:16:46 +08:00
0503c17867 feat/gfcli: replace gofmt&goimports with tools/imports (#1935) 2022-06-24 14:15:20 +08:00
19779cd342 Fix multiple gdb-group overrides (#1890)
Co-authored-by: longl <longlei@dealmap.cloud>
2022-06-23 21:30:29 +08:00
141f3512a9 fix glog bug (#1844) 2022-06-23 21:05:12 +08:00
3b9e5c71bf version updates 2022-06-21 21:52:54 +08:00
2bcee014f7 add tracing feature for package gproc (#1923) 2022-06-21 21:46:12 +08:00
f0568b4e22 Merge branch 'develop' 2022-06-21 19:08:36 +08:00
8670f29c4e update project templates and improve command init for cli 2022-06-21 18:08:11 +08:00
33a528af76 fix issue #1913 2022-06-20 22:03:19 +08:00
52056644d4 add context parameter (#1919) 2022-06-20 20:34:59 +08:00
3ae23df4b3 Improve the code coverage of the gmap module (#1910) 2022-06-20 19:05:47 +08:00
1b327b8abd improve database configuration parsing for package gins/gdb 2022-06-20 12:07:51 +08:00
bb5cd3e224 fix database configuration parsing for package gins 2022-06-20 11:14:13 +08:00
1e8237446e add tracing logging content if trace id is available in context for package gcmd 2022-06-17 17:42:49 +08:00
b2b2044786 add tracing logging content if trace id is available in context for package gcmd 2022-06-17 17:41:10 +08:00
64c5222623 add environment support of opentelemetry propagation for package gctx 2022-06-17 16:47:01 +08:00
1597291ac3 improve configuration parsing for package gdb 2022-06-17 15:35:55 +08:00
c2e742335b add otel support for package gcmd 2022-06-17 15:16:35 +08:00
cf5884bc60 add SetBodyContent for gclient.Response 2022-06-17 11:31:32 +08:00
cbf5ee9649 go fmt -w 2022-06-16 18:02:51 +08:00
8ac177a6de improve UT for package gredis 2022-06-16 17:41:15 +08:00
cdd4473df5 improve command gen service; add error trace for error of some packages 2022-06-16 17:07:25 +08:00
aaebaa7250 improve DoRequestObj for gclient.Client 2022-06-16 10:51:12 +08:00
7443a8baa1 Merge branch 'develop' 2022-06-15 21:43:04 +08:00
c6ff95a3f4 README update for contrib/registry etcd/polaris 2022-06-15 21:42:12 +08:00
7957016ae2 Polaris Server Offical image support (#1911) 2022-06-15 19:38:22 +08:00
17ab0e2ced remove returning error of Write* functions for ghttp.Server; add UT cases for gclient.Client.DoRequestObj 2022-06-15 19:36:53 +08:00
b0650f3402 Improve the code coverage of the garray,glist module (#1908) 2022-06-15 19:35:21 +08:00
f4f73f2765 Merge branch 'master' of https://github.com/gogf/gf into develop 2022-06-15 16:28:20 +08:00
babc69e13d add DoRequestObj function for gclient.Client 2022-06-15 16:28:17 +08:00
481c50f233 add example for package gerror 2022-06-15 14:46:31 +08:00
b62b2f3598 Improve the code coverage of the gudp module (#1907) 2022-06-13 22:01:20 +08:00
4f37abac6a upgrade ClickHouse-Go dependencies to V2.0.15 (#1904) 2022-06-13 19:40:47 +08:00
31a23e724d Improve the code coverage of the gclient module (#1899) 2022-06-13 19:31:42 +08:00
7d5ab1f8db Merge branch 'master' of https://github.com/gogf/gf 2022-06-06 21:36:44 +08:00
0d8952dcde improve WithTraceID function for package gtrace 2022-06-06 21:36:30 +08:00
bd7ec5d0b0 Feature/sqlite ut (#1882) 2022-06-06 19:57:53 +08:00
MZ
9e6e8001ca fix gf gen service ignore watch file dir windows platform bug (#1889) 2022-06-06 19:56:44 +08:00
0639becccc version updates 2022-06-01 16:36:40 +08:00
88844649eb fix version of redoc 2022-06-01 16:34:07 +08:00
31c5d5a5f5 Merge branch 'master' of https://github.com/gogf/gf into develop 2022-06-01 14:44:11 +08:00
6abbc57c96 fix issue #1864 2022-05-26 15:28:17 +08:00
39af6e51c4 fix ut cases for package goai 2022-05-26 15:17:59 +08:00
ef04c8a09e Feature/oracle (#1869) 2022-05-25 21:55:27 +08:00
4505d61604 improve WhereBuilder feature for package gdb 2022-05-25 21:52:08 +08:00
04d32e7a91 improve FieldsPrefix for gdb.Model 2022-05-25 16:22:46 +08:00
26066965c3 Merge branch 'master' of https://github.com/gogf/gf into develop 2022-05-25 16:02:48 +08:00
7f199527f8 improve service discovery for package gclient 2022-05-24 19:16:43 +08:00
ea79b3cbb8 move package goai from protocol to net 2022-05-24 18:53:10 +08:00
0ca81bd11a Improve the code coverage of the gtcp module (#1836) 2022-05-23 22:45:12 +08:00
4d13ffdc26 improve ut case for empty upload file validation 2022-05-23 22:23:29 +08:00
331a29024e merge master 2022-05-23 22:17:06 +08:00
6aa5c2b2ef Fix/1748 issues #1748 (#1817) 2022-05-23 22:09:11 +08:00
8c969b2a84 upgrade ClickHouse dependencies to V2 (#1772) 2022-05-23 21:21:59 +08:00
0d7e28ee75 add deep copy feature 2022-05-23 16:51:10 +08:00
ab5062663e Feature/gsvc interface (#1871) 2022-05-23 15:08:11 +08:00
896b9fa105 [ISSUE #1866] Fix/polaris logs dir and docker image (#1867)
* feat:modify polaris log dir

* modify polaris image docker

* fix: modify polaris docker image
2022-05-19 23:33:04 +08:00
6a01275499 improve data converting for package gdb 2022-05-19 21:44:53 +08:00
61bf0a0092 remove sqlite import for command gen dao 2022-05-19 20:13:56 +08:00
d7c5a08d20 fix issue of space char in binary pth of gofmt/goimports 2022-05-19 20:03:44 +08:00
350ee9f0a2 ci workflow updates 2022-05-19 19:59:41 +08:00
7753fc6fe1 improve error message for package gdb 2022-05-19 17:27:13 +08:00
24f5b2782d version updates 2022-05-19 16:10:52 +08:00
853d7aaf8f fix issue missing mysql driver import for package contrib/drivers/mysql 2022-05-19 15:02:15 +08:00
07509e9847 go mod tidy 2022-05-19 10:49:09 +08:00
ab82599ee2 Feature/polaris feat: Add Polaris support (#1797) 2022-05-18 22:24:40 +08:00
10e2b60ad9 workflow ci updates 2022-05-18 21:38:13 +08:00
965476c7f4 workflow ci updates 2022-05-18 21:24:15 +08:00
9536b33a6a Fix/codecovci (#1858) 2022-05-18 21:18:49 +08:00
61271e4f7b Replace the Swagger JS CDN source from jsdelivr to unpkg.com (#1852)
replace the CDN source from jsdelivr to unpkg.com

The jsdelivr cdn certificate expired in the mainland, causing the website to hang. To fix it, the solution is to replace the CDN source to unpkg.com
2022-05-18 20:34:59 +08:00
57941b6df9 Bug fix#1849 (#1851) 2022-05-18 20:19:40 +08:00
1102de5a66 fix issue in missing mysql import for command gen dao 2022-05-18 20:02:53 +08:00
6d33a73617 Merge branch 'master' of https://github.com/gogf/gf 2022-05-18 19:58:25 +08:00
cdcb0cdc14 Merge branch 'develop' 2022-05-18 19:58:16 +08:00
6176028176 improve package gmeta 2022-05-18 17:57:16 +08:00
c871bb3a1e improve package gcfg 2022-05-18 15:11:49 +08:00
3430cf1f17 improve data converting for package gdb, drivers/pgsql 2022-05-18 11:55:09 +08:00
4556dda038 improve data converting for package gdb, drivers/pgsql 2022-05-18 11:16:25 +08:00
49042d480c improve data converting for package gdb, drivers/pgsql 2022-05-18 11:05:05 +08:00
b7295a1558 Merge pull request #1843 from wenzi1/feature/mssql
mssql unit test
2022-05-17 21:24:50 +08:00
ec0cbab47e Merge remote-tracking branch 'origin/master' into feature/mssql 2022-05-17 09:42:21 +08:00
8e3c66584d add unit test 2022-05-16 22:58:53 +08:00
26d460241d Null in field is error 2022-05-13 23:30:33 +08:00
ede54b392e Merge branch 'master' of https://github.com/wenzi1/gf 2022-05-13 23:13:07 +08:00
d12542d78e Merge remote-tracking branch 'origin/master' 2022-05-13 22:20:50 +08:00
cb27f26e64 Merge branch 'gogf:master' into master 2022-05-13 22:00:49 +08:00
cf57ea3ef0 Merge branch 'gogf:master' into master 2022-05-13 21:51:08 +08:00
27836feb47 delete comment 2022-05-13 21:45:19 +08:00
96e48e1de6 Merge branch 'master' into feature/mssql 2022-05-13 21:07:34 +08:00
9fcd3374c1 Merge pull request #1827 from wenzi1/feature/mssql
Feature/mssql
2022-05-12 11:47:28 +08:00
3b8853736d Merge branch 'develop' into master 2022-05-12 09:25:25 +08:00
16b22e7505 add unit test 2022-05-12 09:03:55 +08:00
72b58ff8a1 add unit test 2022-05-12 00:03:20 +08:00
900e0b2751 add gini 2022-05-12 00:00:36 +08:00
284 changed files with 21378 additions and 2369 deletions

View File

@ -8,6 +8,7 @@ on:
- develop
- feature/**
- fix/**
pull_request:
branches:
- master
@ -27,7 +28,7 @@ jobs:
services:
# Redis backend server.
redis:
image : redis
image : loads/redis:latest
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
@ -39,7 +40,7 @@ jobs:
# MySQL backend server.
mysql:
image: mysql:5.7
image: loads/mysql:5.7
env:
MYSQL_DATABASE : test
MYSQL_ROOT_PASSWORD: 12345678
@ -49,7 +50,7 @@ jobs:
# PostgreSQL backend server.
postgres:
image: postgres:13
image: loads/postgres:13
env:
POSTGRES_PASSWORD: 12345678
POSTGRES_USER: root
@ -66,7 +67,7 @@ jobs:
# MSSQL backend server.
mssql:
image: mcmoe/mssqldocker:latest
image: loads/mssqldocker:latest
env:
ACCEPT_EULA: Y
SA_PASSWORD: LoremIpsum86
@ -84,16 +85,35 @@ jobs:
# ClickHouse backend server.
clickhouse-server:
image: yandex/clickhouse-server
image: loads/clickhouse-server:latest
ports:
- 9000:9000
- 8123:8123
- 9001:9001
polaris:
image: polarismesh/polaris-server-standalone:latest
ports:
- 8090:8090
- 8091:8091
#oracle 11g server
oracle-server:
image: loads/oracle-xe-11g-r2:latest
env:
ORACLE_ALLOW_REMOTE: true
ORACLE_SID: XE
ORACLE_DB_USER_NAME: system
ORACLE_DB_PASSWORD: oracle
ports:
- 1521:1521
strategy:
matrix:
go: ["1.15", "1.16", "1.17"]
go: [ "1.15", "1.16", "1.17" ]
goarch: [ "386", "amd64" ]
steps:
@ -117,47 +137,30 @@ jobs:
echo "gofmt check pass."
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
- name: CLI Build & Test
- name: Build & Test
run: |
cd cmd/gf
go mod tidy
go build ./...
GOARCH=386 go test -v ./... || exit 1
GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
- name: Example Build & Test
run: |
cd example
go mod tidy
go build ./...
GOARCH=386 go test -v ./... || exit 1
GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
- name: Contrib Build & Test
run: |
cd contrib
GOARCH=${{ matrix.goarch }}
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
# Ignore oracle database driver build&test.
if [ "oracle" = $(basename $dirpath) ]; then
continue 1
if ! go version|grep -q "1.17"; then
continue 1
fi
fi
cd $dirpath
go mod tidy
go build ./...
GOARCH=386 go test -v ./... || exit 1
GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
go test ./... -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
if grep -q "/gogf/gf/.*/v2" go.mod; then
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
fi
cd -
done
- name: Main Build & Test
run: |
go build ./...
GOARCH=386 go test -v ./... || exit 1
GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
- name: Report Coverage
uses: codecov/codecov-action@v2
with:
flags: go-${{ matrix.go }}
flags: go-${{ matrix.go }}-${{ matrix.goarch }}

2
.gitignore vendored
View File

@ -15,3 +15,5 @@ cbuild
**/.DS_Store
.test/
cmd/gf/main
cmd/gf/gf
go.work

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,17 @@ module github.com/gogf/gf/cmd/gf/v2
go 1.15
require (
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.0.6
github.com/gogf/gf/v2 v2.0.6
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.1.0
github.com/gogf/gf/v2 v2.1.0
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/tools v0.1.11
)
replace (
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql/
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle/
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql/
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql/
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/
github.com/gogf/gf/v2 => ../../

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -22,8 +25,10 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@ -41,14 +46,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
@ -60,8 +66,6 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk=
github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -69,12 +73,16 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -83,6 +91,7 @@ github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMT
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
@ -92,17 +101,22 @@ go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -115,6 +129,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -123,20 +138,26 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -206,11 +206,14 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
}
packCmd := fmt.Sprintf(`gf pack %s %s`, in.PackSrc, in.PackDst)
mlog.Print(packCmd)
gproc.MustShellRun(packCmd)
gproc.MustShellRun(ctx, packCmd)
}
// Injected information by building flags.
ldFlags := fmt.Sprintf(`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`, c.getBuildInVarStr(in))
ldFlags := fmt.Sprintf(
`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`,
c.getBuildInVarStr(ctx, in),
)
// start building
mlog.Print("start building...")
@ -261,7 +264,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
// It's not necessary printing the complete command string.
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
mlog.Print(cmdShow)
if result, err := gproc.ShellExec(cmd); err != nil {
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
mlog.Printf(
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
system, arch, gstr.Trim(result),
@ -287,12 +290,12 @@ buildDone:
// getBuildInVarMapJson retrieves and returns the custom build-in variables in configuration
// file as json.
func (c cBuild) getBuildInVarStr(in cBuildInput) string {
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
buildInVarMap := in.VarMap
if buildInVarMap == nil {
buildInVarMap = make(g.Map)
}
buildInVarMap["builtGit"] = c.getGitCommit()
buildInVarMap["builtGit"] = c.getGitCommit(ctx)
buildInVarMap["builtTime"] = gtime.Now().String()
b, err := json.Marshal(buildInVarMap)
if err != nil {
@ -302,13 +305,13 @@ func (c cBuild) getBuildInVarStr(in cBuildInput) string {
}
// getGitCommit retrieves and returns the latest git commit hash string if present.
func (c cBuild) getGitCommit() string {
func (c cBuild) getGitCommit(ctx context.Context) string {
if gproc.SearchBinary("git") == "" {
return ""
}
var (
cmd = `git log -1 --format="%cd %H" --date=format:"%Y-%m-%d %H:%M:%S"`
s, _ = gproc.ShellExec(cmd)
s, _ = gproc.ShellExec(ctx, cmd)
)
mlog.Debug(cmd)
if s != "" {

View File

@ -88,14 +88,14 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
// Binary build.
in.Build += " --exit"
if in.Main != "" {
if err = gproc.ShellRun(fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
if err = gproc.ShellRun(ctx, fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
return
}
}
// Shell executing.
if in.Shell != "" && gfile.Exists(in.Shell) {
if err = c.exeDockerShell(in.Shell); err != nil {
if err = c.exeDockerShell(ctx, in.Shell); err != nil {
return
}
}
@ -116,7 +116,7 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
}
for i, dockerTag := range dockerTags {
if i > 0 {
err = gproc.ShellRun(fmt.Sprintf(`docker tag %s %s`, dockerTagBase, dockerTag))
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker tag %s %s`, dockerTagBase, dockerTag))
if err != nil {
return
}
@ -130,7 +130,7 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
if in.Extra != "" {
dockerBuildOptions = fmt.Sprintf(`%s %s`, dockerBuildOptions, in.Extra)
}
err = gproc.ShellRun(fmt.Sprintf(`docker build -f %s . %s`, in.File, dockerBuildOptions))
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker build -f %s . %s`, in.File, dockerBuildOptions))
if err != nil {
return
}
@ -144,7 +144,7 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
if dockerTag == "" {
continue
}
err = gproc.ShellRun(fmt.Sprintf(`docker push %s`, dockerTag))
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker push %s`, dockerTag))
if err != nil {
return
}
@ -152,10 +152,10 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
return
}
func (c cDocker) exeDockerShell(shellFilePath string) error {
func (c cDocker) exeDockerShell(ctx context.Context, shellFilePath string) error {
if gfile.ExtName(shellFilePath) == "sh" && runtime.GOOS == "windows" {
mlog.Debugf(`ignore shell file "%s", as it cannot be run on windows system`, shellFilePath)
return nil
}
return gproc.ShellRun(gfile.GetContents(shellFilePath))
return gproc.ShellRun(ctx, gfile.GetContents(shellFilePath))
}

View File

@ -26,7 +26,7 @@ type cEnvInput struct {
type cEnvOutput struct{}
func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) {
result, err := gproc.ShellExec("go env")
result, err := gproc.ShellExec(ctx, "go env")
if err != nil {
mlog.Fatal(err)
}

View File

@ -11,6 +11,10 @@ var (
type cGen struct {
g.Meta `name:"gen" brief:"{cGenBrief}" dc:"{cGenDc}"`
cGenDao
cGenPb
cGenPbEntity
cGenService
}
const (

View File

@ -20,8 +20,9 @@ import (
"github.com/olekukonko/tablewriter"
_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
//_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
//_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
)
@ -137,6 +138,7 @@ func init() {
}
type (
cGenDao struct{}
cGenDaoInput struct {
g.Meta `name:"dao" config:"{cGenDaoConfig}" usage:"{cGenDaoUsage}" brief:"{cGenDaoBrief}" eg:"{cGenDaoEg}" ad:"{cGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{cGenDaoBriefPath}" d:"internal"`
@ -169,7 +171,7 @@ type (
}
)
func (c cGen) Dao(ctx context.Context, in cGenDaoInput) (out *cGenDaoOutput, err error) {
func (c cGenDao) Dao(ctx context.Context, in cGenDaoInput) (out *cGenDaoOutput, err error) {
if g.Cfg().Available(ctx) {
v := g.Cfg().MustGet(ctx, cGenDaoConfig)
if v.IsSlice() {

View File

@ -13,13 +13,14 @@ import (
)
type (
cGenPb struct{}
cGenPbInput struct {
g.Meta `name:"pb" brief:"parse proto files and generate protobuf go files"`
}
cGenPbOutput struct{}
)
func (c cGen) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err error) {
func (c cGenPb) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err error) {
// Necessary check.
if gproc.SearchBinary("protoc") == "" {
mlog.Fatalf(`command "protoc" not found in your environment, please install protoc first to proceed this command`)
@ -56,7 +57,7 @@ func (c cGen) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err er
parsingCommand += " -I" + goPathSrc
}
mlog.Print(parsingCommand)
if output, err := gproc.ShellExec(parsingCommand); err != nil {
if output, err := gproc.ShellExec(ctx, parsingCommand); err != nil {
mlog.Print(output)
mlog.Fatal(err)
}

View File

@ -19,6 +19,29 @@ import (
"github.com/olekukonko/tablewriter"
)
type (
cGenPbEntity struct{}
cGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{cGenPbEntityConfig}" brief:"{cGenPbEntityBrief}" eg:"{cGenPbEntityEg}" ad:"{cGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{cGenPbEntityBriefPath}"`
Package string `name:"package" short:"k" brief:"{cGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{cGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{cGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{cGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{cGenPbEntityBriefOption}"`
}
cGenPbEntityOutput struct{}
cGenPbEntityInternalInput struct {
cGenPbEntityInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
}
)
const (
cGenPbEntityConfig = `gfcli.gen.pbentity`
cGenPbEntityBrief = `generate entity message files in protobuf3 format`
@ -83,28 +106,6 @@ set it to "none" to ignore json tag generating.
`
)
type (
cGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{cGenPbEntityConfig}" brief:"{cGenPbEntityBrief}" eg:"{cGenPbEntityEg}" ad:"{cGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{cGenPbEntityBriefPath}"`
Package string `name:"package" short:"k" brief:"{cGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{cGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{cGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{cGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{cGenPbEntityBriefOption}"`
}
cGenPbEntityOutput struct{}
cGenPbEntityInternalInput struct {
cGenPbEntityInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
}
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenPbEntityConfig`: cGenPbEntityConfig,
@ -124,7 +125,7 @@ func init() {
})
}
func (c cGen) PbEntity(ctx context.Context, in cGenPbEntityInput) (out *cGenPbEntityOutput, err error) {
func (c cGenPbEntity) PbEntity(ctx context.Context, in cGenPbEntityInput) (out *cGenPbEntityOutput, err error) {
var (
config = g.Cfg()
)

View File

@ -18,15 +18,16 @@ import (
)
type (
cGenService struct{}
cGenServiceInput struct {
g.Meta `name:"service" config:"gfcli.gen.service" brief:"parse struct and associated functions from packages to generate service go file"`
SrcFolder string `short:"s" name:"srcFolder" brief:"source folder path to be parsed. default: internal/logic" d:"internal/logic"`
DstFolder string `short:"d" name:"dstFolder" brief:"destination folder path storing automatically generated go files. default: internal/service" d:"internal/service"`
WatchFile string `short:"w" name:"watchFile" brief:"used in file watcher, it generates service go files only if given file is under srcFolder"`
StPattern string `short:"a" name:"stPattern" brief:"regular expression matching struct name for generating service. default: s([A-Z]\\w+)" d:"s([A-Z]\\w+)"`
Packages string `short:"p" name:"packages" brief:"produce go files only for given source packages, multiple packages joined with char ','"`
ImportPrefix string `short:"i" name:"importPrefix" brief:"custom import prefix to calculate import path for generated importing go file of logic"`
OverWrite bool `short:"o" name:"overwrite" brief:"overwrite service go files that already exist in generating folder. default: true" d:"true" orphan:"true"`
SrcFolder string `short:"s" name:"srcFolder" brief:"source folder path to be parsed. default: internal/logic" d:"internal/logic"`
DstFolder string `short:"d" name:"dstFolder" brief:"destination folder path storing automatically generated go files. default: internal/service" d:"internal/service"`
WatchFile string `short:"w" name:"watchFile" brief:"used in file watcher, it generates service go files only if given file is under srcFolder"`
StPattern string `short:"a" name:"stPattern" brief:"regular expression matching struct name for generating service. default: s([A-Z]\\\\w+)" d:"s([A-Z]\\w+)"`
Packages []string `short:"p" name:"packages" brief:"produce go files only for given source packages"`
ImportPrefix string `short:"i" name:"importPrefix" brief:"custom import prefix to calculate import path for generated importing go file of logic"`
OverWrite bool `short:"o" name:"overwrite" brief:"overwrite service go files that already exist in generating folder. default: true" d:"true" orphan:"true"`
}
cGenServiceOutput struct{}
)
@ -35,7 +36,7 @@ const (
genServiceFileLockSeconds = 10
)
func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServiceOutput, err error) {
func (c cGenService) Service(ctx context.Context, in cGenServiceInput) (out *cGenServiceOutput, err error) {
// File lock to avoid multiple processes.
var (
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
@ -65,7 +66,7 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
)
mlog.Debug("watchFileDir:", watchFileDir)
mlog.Debug("logicFolderDir:", srcFolderDir)
if !gstr.HasSuffix(srcFolderDir, in.SrcFolder) {
if !gstr.HasSuffix(gstr.Replace(srcFolderDir, `\`, `/`), in.SrcFolder) {
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
return
}
@ -79,7 +80,7 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
`%s gen service -packages=%s`,
gfile.SelfName(), gfile.Basename(watchFileDir),
)
err = gproc.ShellRun(command)
err = gproc.ShellRun(ctx, command)
return
}
@ -101,13 +102,12 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
}
var (
isDirty bool
files []string
fileContent string
matches [][]string
importSrcPackages []string
inputPackages = gstr.SplitAndTrim(in.Packages, ",")
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder))
isDirty bool
files []string
fileContent string
initImportSrcPackages []string
inputPackages = in.Packages
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder))
)
srcFolders, err := gfile.ScanDir(in.SrcFolder, "*", false)
if err != nil {
@ -125,56 +125,25 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
}
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
srcPkgInterfaceFuncArray *garray.StrArray
ok bool
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
ok bool
)
for _, file := range files {
fileContent = gfile.GetContents(file)
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
// Calculate imported packages of source go files.
err = c.calculateImportedPackages(fileContent, srcImportedPackages)
if err != nil {
return nil, err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return nil, err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
}
// Remove package name calls of `dstPackageName` in produced codes.
functionHead, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, functionHead)
srcPkgInterfaceFuncArray.Append(functionHead)
// Calculate functions and interfaces for service generating.
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap, dstPackageName)
if err != nil {
return nil, err
}
}
importSrcPackages = append(
importSrcPackages,
initImportSrcPackages = append(
initImportSrcPackages,
fmt.Sprintf(`%s/%s`, in.ImportPrefix, gfile.Basename(srcFolder)),
)
// Ignore source packages if input packages given.
@ -186,7 +155,7 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
continue
}
// Generating go files for service.
if ok, err = c.generateServiceFiles(in, srcPkgInterfaceMap, dstPackageName); err != nil {
if ok, err = c.generateServiceFiles(in, srcPkgInterfaceMap, srcImportedPackages.Slice(), dstPackageName); err != nil {
return
}
if ok {
@ -196,8 +165,8 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
if isDirty {
// Generate initialization go file.
if len(importSrcPackages) > 0 {
if err = c.generateInitializationFile(in, importSrcPackages); err != nil {
if len(initImportSrcPackages) > 0 {
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
return
}
}
@ -218,13 +187,86 @@ func (c cGen) Service(ctx context.Context, in cGenServiceInput) (out *cGenServic
return
}
func (c cGen) generateServiceFiles(
in cGenServiceInput, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
func (c cGenService) calculateImportedPackages(fileContent string, srcImportedPackages *garray.SortedStrArray) (err error) {
var match []string
match, err = gregex.MatchString(`\s+import\s+\(([\s\S]+?)\)`, fileContent)
if err != nil {
return err
}
if len(match) < 2 {
return nil
}
importPart := gstr.Trim(match[1])
srcImportedPackages.Append(gstr.SplitAndTrim(importPart, "\n")...)
return nil
}
func (c cGenService) calculateInterfaceFunctions(
in cGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
) (err error) {
var (
ok bool
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
}
// Remove package name calls of `dstPackageName` in produced codes.
functionHead, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, functionHead)
srcPkgInterfaceFuncArray.Append(functionHead)
}
return nil
}
func (c cGenService) generateServiceFiles(
in cGenServiceInput,
srcPkgInterfaceMap map[string]*garray.StrArray,
srcImportedPackages []string,
dstPackageName string,
) (ok bool, err error) {
srcImportedPackagesContent := fmt.Sprintf(
"import (\n%s\n)", gstr.Join(srcImportedPackages, "\n"),
)
for structName, funcArray := range srcPkgInterfaceMap {
var (
filePath = gfile.Join(in.DstFolder, gstr.ToLower(structName)+".go")
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceContent, g.MapStrStr{
"{Imports}": srcImportedPackagesContent,
"{StructName}": structName,
"{PackageName}": dstPackageName,
"{FuncDefinition}": funcArray.Join("\n\t"),
@ -250,7 +292,7 @@ func (c cGen) generateServiceFiles(
}
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
func (c cGen) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrArray) bool {
func (c cGenService) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrArray) bool {
if !utils.IsFileDoNotEdit(filePath) {
mlog.Debugf(`ignore file as it is manually maintained: %s`, filePath)
return false
@ -280,7 +322,7 @@ func (c cGen) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrAr
return false
}
func (c cGen) generateInitializationFile(in cGenServiceInput, importSrcPackages []string) (err error) {
func (c cGenService) generateInitializationFile(in cGenServiceInput, importSrcPackages []string) (err error) {
var (
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
@ -306,7 +348,7 @@ func (c cGen) generateInitializationFile(in cGenServiceInput, importSrcPackages
return nil
}
func (c cGen) replaceGeneratedServiceContentGFV2(in cGenServiceInput) (err error) {
func (c cGenService) replaceGeneratedServiceContentGFV2(in cGenServiceInput) (err error) {
return gfile.ReplaceDirFunc(func(path, content string) string {
if gstr.Contains(content, `"github.com/gogf/gf`) && !gstr.Contains(content, `"github.com/gogf/gf/v2`) {
content = gstr.Replace(content, `"github.com/gogf/gf"`, `"github.com/gogf/gf/v2"`)

View File

@ -10,6 +10,7 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag"
)
@ -48,7 +49,8 @@ func init() {
type cInitInput struct {
g.Meta `name:"init"`
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
}
type cInitOutput struct{}
@ -89,6 +91,18 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
return
}
// Update the GoFrame version.
if in.Update {
mlog.Print("update goframe...")
updateCommand := `go get -u github.com/gogf/gf/v2@latest`
if in.Name != "." {
updateCommand = fmt.Sprintf(`cd %s && %s`, in.Name, updateCommand)
}
if err = gproc.ShellRun(ctx, updateCommand); err != nil {
mlog.Fatal(err)
}
}
mlog.Print("initialization done! ")
if !in.Mono {
enjoyCommand := `gf run main.go`

View File

@ -99,17 +99,17 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`go file changes: %s`, event.String())
app.Run()
app.Run(ctx)
})
})
if err != nil {
mlog.Fatal(err)
}
go app.Run()
go app.Run(ctx)
select {}
}
func (app *cRunApp) Run() {
func (app *cRunApp) Run(ctx context.Context) {
// Rebuild and run the codes.
renamePath := ""
mlog.Printf("build: %s", app.File)
@ -132,7 +132,7 @@ func (app *cRunApp) Run() {
app.File,
)
mlog.Print(buildCommand)
result, err := gproc.ShellExec(buildCommand)
result, err := gproc.ShellExec(ctx, buildCommand)
if err != nil {
mlog.Printf("build error: \n%s%s", result, err.Error())
return
@ -154,7 +154,7 @@ func (app *cRunApp) Run() {
} else {
process = gproc.NewProcessCmd(outputPath, gstr.SplitAndTrim(" ", app.Args))
}
if pid, err := process.Start(); err != nil {
if pid, err := process.Start(ctx); err != nil {
mlog.Printf("build running error: %s", err.Error())
} else {
mlog.Printf("build running pid: %d", pid)

View File

@ -7,6 +7,8 @@ const TemplateGenServiceContent = `
package {PackageName}
{Imports}
type I{StructName} interface {
{FuncDefinition}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,41 +1,24 @@
package utils
import (
"fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr"
"golang.org/x/tools/imports"
)
var (
gofmtPath = gproc.SearchBinaryPath("gofmt") // gofmtPath is the binary path of command `gofmt`.
goimportsPath = gproc.SearchBinaryPath("goimports") // gofmtPath is the binary path of command `goimports`.
)
// GoFmt formats the source file using command `gofmt -w -s PATH`.
// GoFmt formats the source file.
func GoFmt(path string) {
if gofmtPath == "" {
mlog.Fatal(`command "gofmt" not found`)
}
var command = fmt.Sprintf(`%s -w %s`, gofmtPath, path)
result, err := gproc.ShellExec(command)
if err != nil {
mlog.Fatalf(`error executing command "%s": %s`, command, result)
if err := pretty(path, true); err != nil {
mlog.Fatalf(`error format "%s" go files: %v`, path, err)
}
}
// GoImports formats the source file using command `goimports -w PATH`.
// GoImports adds or removes import statements as necessary for the source file.
func GoImports(path string) {
if goimportsPath == "" {
mlog.Fatal(`command "goimports" not found`)
}
var command = fmt.Sprintf(`%s -w %s`, goimportsPath, path)
result, err := gproc.ShellExec(command)
if err != nil {
mlog.Fatalf(`error executing command "%s": %s`, command, result)
if err := pretty(path); err != nil {
mlog.Fatalf(`error update "%s" go file imports: %v`, path, err)
}
}
@ -46,3 +29,31 @@ func IsFileDoNotEdit(filePath string) bool {
}
return gstr.Contains(gfile.GetContents(filePath), consts.DoNotEditKey)
}
// pretty format go file and adds or removes import statements as necessary.
func pretty(filePath string, formatOnly ...bool) error {
var genOpt *imports.Options
if len(formatOnly) > 0 {
genOpt = &imports.Options{
Comments: true,
TabIndent: true,
TabWidth: 8,
FormatOnly: true,
}
}
replaceFunc := func(path, content string) string {
res, err := imports.Process(path, []byte(content), genOpt)
if err != nil {
mlog.Printf(`pretty go file "%s" failed: %v`, path, err)
return content
}
return string(res)
}
if gfile.IsFile(filePath) {
if gfile.ExtName(filePath) != "go" {
return nil
}
return gfile.ReplaceFileFunc(replaceFunc, filePath)
}
return gfile.ReplaceDirFunc(replaceFunc, filePath, "*.go", true)
}

View File

@ -14,6 +14,7 @@ import (
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -820,3 +821,14 @@ func (a *Array) Walk(f func(value interface{}) interface{}) *Array {
func (a *Array) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *Array) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]interface{}, len(a.array))
for i, v := range a.array {
newSlice[i] = deepcopy.Copy(v)
}
return NewArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -799,3 +799,12 @@ func (a *IntArray) Walk(f func(value int) int) *IntArray {
func (a *IntArray) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *IntArray) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]int, len(a.array))
copy(newSlice, a.array)
return NewIntArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -812,3 +812,12 @@ func (a *StrArray) Walk(f func(value string) string) *StrArray {
func (a *StrArray) IsEmpty() bool {
return a.Len() == 0
}
// DeepCopy implements interface for deep copy of current type.
func (a *StrArray) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]string, len(a.array))
copy(newSlice, a.array)
return NewStrArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -12,6 +12,7 @@ import (
"math"
"sort"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -796,3 +797,14 @@ func (a *SortedArray) getComparator() func(a, b interface{}) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedArray) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]interface{}, len(a.array))
for i, v := range a.array {
newSlice[i] = deepcopy.Copy(v)
}
return NewSortedArrayFrom(newSlice, a.comparator, a.mu.IsSafe())
}

View File

@ -744,3 +744,12 @@ func (a *SortedIntArray) getComparator() func(a, b int) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedIntArray) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]int, len(a.array))
copy(newSlice, a.array)
return NewSortedIntArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -757,3 +757,12 @@ func (a *SortedStrArray) getComparator() func(a, b string) int {
}
return a.comparator
}
// DeepCopy implements interface for deep copy of current type.
func (a *SortedStrArray) DeepCopy() interface{} {
a.mu.RLock()
defer a.mu.RUnlock()
newSlice := make([]string, len(a.array))
copy(newSlice, a.array)
return NewSortedStrArrayFrom(newSlice, a.mu.IsSafe())
}

View File

@ -46,6 +46,8 @@ func ExampleNew() {
a.Set(0, 100)
fmt.Println(a.Slice())
fmt.Println(a.At(0))
// Search item and return its index.
fmt.Println(a.Search(5))
@ -66,6 +68,7 @@ func ExampleNew() {
// false
// [0 1 2 3 4 5 6 7 8 9 10 11]
// [100 1 2 3 4 5 6 7 8 9 10 11]
// 100
// 5
// [1 2 3 4 5 6 7 8 9 10 11]
// [1 2 3 4 5 6 7 8 9 10 11]

View File

@ -54,6 +54,14 @@ func ExampleNewIntArraySize() {
// [10 20 15] 3 5
}
func ExampleNewIntArrayRange() {
s := garray.NewIntArrayRange(1, 5, 1)
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
// Output:
// [1 2 3 4 5] 5 5
}
func ExampleNewIntArrayFrom() {
s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30})
fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
@ -83,9 +91,12 @@ func ExampleIntArray_Get() {
s := garray.NewIntArrayFrom(g.SliceInt{10, 20, 15, 30})
sGet, sBool := s.Get(3)
fmt.Println(sGet, sBool)
sGet, sBool = s.Get(99)
fmt.Println(sGet, sBool)
// Output:
// 30 true
// 0 false
}
func ExampleIntArray_Set() {

View File

@ -25,9 +25,24 @@ func Test_Array_Basic(t *testing.T) {
array := garray.NewArrayFrom(expect)
array2 := garray.NewArrayFrom(expect)
array3 := garray.NewArrayFrom([]interface{}{})
array4 := garray.NewArrayRange(1, 5, 1)
t.Assert(array.Slice(), expect)
t.Assert(array.Interfaces(), expect)
array.Set(0, 100)
err := array.Set(0, 100)
t.AssertNil(err)
err = array.Set(100, 100)
t.AssertNE(err, nil)
t.Assert(array.IsEmpty(), false)
copyArray := array.DeepCopy()
ca := copyArray.(*garray.Array)
ca.Set(0, 1)
cval, _ := ca.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
v, ok := array.Get(0)
t.Assert(v, 100)
@ -37,6 +52,10 @@ func Test_Array_Basic(t *testing.T) {
t.Assert(v, 1)
t.Assert(ok, true)
v, ok = array.Get(4)
t.Assert(v, nil)
t.Assert(ok, false)
t.Assert(array.Search(100), 0)
t.Assert(array3.Search(100), -1)
t.Assert(array.Contains(100), true)
@ -71,6 +90,12 @@ func Test_Array_Basic(t *testing.T) {
array.InsertAfter(6, 400)
t.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
err = array.InsertBefore(99, 9900)
t.AssertNE(err, nil)
err = array.InsertAfter(99, 9900)
t.AssertNE(err, nil)
t.Assert(array4.String(), "[1,2,3,4,5]")
})
}
@ -99,6 +124,11 @@ func TestArray_Unique(t *testing.T) {
array := garray.NewArrayFrom(expect)
t.Assert(array.Unique().Slice(), []interface{}{1, 2, 3, 4, 5})
})
gtest.C(t, func(t *gtest.T) {
expect := []interface{}{}
array := garray.NewArrayFrom(expect)
t.Assert(array.Unique().Slice(), []interface{}{})
})
}
func TestArray_PushAndPop(t *testing.T) {
@ -382,6 +412,21 @@ func TestArray_Rand(t *testing.T) {
t.Assert(a1.Contains(i1), true)
t.Assert(a1.Len(), 4)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
rand, found := array1.Rand()
t.AssertNil(rand)
t.Assert(found, false)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
rand := array1.Rands(1)
t.AssertNil(rand)
})
}
func TestArray_Shuffle(t *testing.T) {
@ -412,6 +457,12 @@ func TestArray_Join(t *testing.T) {
array1 := garray.NewArrayFrom(a1)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewArrayFrom(a1)
t.Assert(len(array1.Join(".")), 0)
})
}
func TestArray_String(t *testing.T) {
@ -419,6 +470,8 @@ func TestArray_String(t *testing.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
t.Assert(array1.String(), `[0,1,2,3,4,5,6]`)
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -63,6 +63,19 @@ func Test_IntArray_Basic(t *testing.T) {
array.InsertAfter(6, 400)
t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
err := array.InsertBefore(99, 300)
t.AssertNE(err, nil)
err = array.InsertAfter(99, 400)
t.AssertNE(err, nil)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom([]int{0, 1, 2, 3})
copyArray := array.DeepCopy().(*garray.IntArray)
copyArray.Set(0, 1)
cval, _ := copyArray.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
})
}
@ -89,6 +102,8 @@ func TestIntArray_Unique(t *testing.T) {
expect := []int{1, 2, 3, 4, 5, 3, 2, 2, 3, 5, 5}
array := garray.NewIntArrayFrom(expect)
t.Assert(array.Unique().Slice(), []int{1, 2, 3, 4, 5})
array2 := garray.NewIntArrayFrom([]int{})
t.Assert(array2.Unique().Slice(), []int{})
})
}
@ -374,6 +389,14 @@ func TestIntArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.AssertIN(v, a1)
t.Assert(ok, true)
array2 := garray.NewIntArrayFrom([]int{})
v, ok = array2.Rand()
t.Assert(v, 0)
t.Assert(ok, false)
intSlices := array2.Rands(1)
t.Assert(intSlices, nil)
})
}
@ -420,6 +443,8 @@ func TestIntArray_String(t *testing.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
t.Assert(array1.String(), "[0,1,2,3,4,5,6]")
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -34,6 +34,10 @@ func Test_StrArray_Basic(t *testing.T) {
t.Assert(v, 100)
t.Assert(ok, true)
v, ok = array3.Get(0)
t.Assert(v, "")
t.Assert(ok, false)
t.Assert(array.Search("100"), 0)
t.Assert(array.Contains("100"), true)
@ -61,12 +65,28 @@ func Test_StrArray_Basic(t *testing.T) {
t.Assert(array.Clear().Len(), 0)
t.Assert(array2.Slice(), expect)
t.Assert(array3.Search("100"), -1)
err := array.InsertBefore(99, "300")
t.AssertNE(err, nil)
array.InsertAfter(99, "400")
t.AssertNE(err, nil)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom([]string{"0", "1", "2", "3"})
copyArray := array.DeepCopy().(*garray.StrArray)
copyArray.Set(0, "1")
cval, _ := copyArray.Get(0)
val, _ := array.Get(0)
t.AssertNE(cval, val)
})
}
func TestStrArray_ContainsI(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := garray.NewStrArray()
t.Assert(s.Contains("A"), false)
s.Append("a", "b", "C")
t.Assert(s.Contains("A"), false)
t.Assert(s.Contains("a"), true)
@ -94,6 +114,8 @@ func TestStrArray_Unique(t *testing.T) {
expect := []string{"1", "1", "2", "2", "3", "3", "2", "2"}
array := garray.NewStrArrayFrom(expect)
t.Assert(array.Unique().Slice(), []string{"1", "2", "3"})
array1 := garray.NewStrArrayFrom([]string{})
t.Assert(array1.Unique().Slice(), []string{})
})
}
@ -364,6 +386,13 @@ func TestStrArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.Assert(ok, true)
t.AssertIN(v, a1)
array2 := garray.NewStrArrayFrom([]string{})
v, ok = array2.Rand()
t.Assert(ok, false)
t.Assert(v, "")
strArray := array2.Rands(1)
t.AssertNil(strArray)
})
}
@ -406,6 +435,11 @@ func TestStrArray_Join(t *testing.T) {
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []string{}
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.Join("."), "")
})
}
func TestStrArray_String(t *testing.T) {
@ -413,6 +447,9 @@ func TestStrArray_String(t *testing.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
t.Assert(array1.String(), `["0","1","2","3","4","5","6"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}

View File

@ -61,6 +61,18 @@ func TestNewSortedArrayFromCopy(t *testing.T) {
})
}
func TestNewSortedArrayRange(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
return gconv.Int(v1) - gconv.Int(v2)
}
array1 := garray.NewSortedArrayRange(1, 5, 1, func1)
t.Assert(array1.Len(), 5)
t.Assert(array1, []interface{}{1, 2, 3, 4, 5})
})
}
func TestSortedArray_SetArray(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
@ -106,10 +118,26 @@ func TestSortedArray_Get(t *testing.T) {
v, ok = array1.Get(1)
t.Assert(v, "c")
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, nil)
t.Assert(ok, false)
})
}
func TestSortedArray_At(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
v := array1.At(2)
t.Assert(v, "f")
})
}
func TestSortedArray_Remove(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
@ -461,6 +489,11 @@ func TestSortedArray_Rand(t *testing.T) {
t.Assert(ok, true)
t.AssertIN(i1, []interface{}{"a", "d", "c"})
t.Assert(array1.Len(), 3)
array2 := garray.NewSortedArrayFrom([]interface{}{}, func1)
v, ok := array2.Rand()
t.Assert(ok, false)
t.Assert(v, nil)
})
}
@ -479,6 +512,10 @@ func TestSortedArray_Rands(t *testing.T) {
i1 = array1.Rands(4)
t.Assert(len(i1), 4)
array2 := garray.NewSortedArrayFrom([]interface{}{}, func1)
v := array2.Rands(1)
t.Assert(v, nil)
})
}
@ -498,6 +535,12 @@ func TestSortedArray_Join(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.Join("."), `"a".0.1.\a`)
})
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.Join("."), "")
})
}
func TestSortedArray_String(t *testing.T) {
@ -505,6 +548,9 @@ func TestSortedArray_String(t *testing.T) {
a1 := []interface{}{0, 1, "a", "b"}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
t.Assert(array1.String(), `[0,1,"a","b"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -541,6 +587,11 @@ func TestSortedArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 5)
t.Assert(array1, []interface{}{1, 2, 3, 4, 5})
array2 := garray.NewSortedArrayFrom([]interface{}{}, gutil.ComparatorInt)
array2.Unique()
t.Assert(array2.Len(), 0)
t.Assert(array2, []interface{}{})
})
}
@ -878,3 +929,22 @@ func TestSortedArray_Walk(t *testing.T) {
}), g.Slice{"key-1", "key-2"})
})
}
func TestSortedArray_IsEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom([]interface{}{}, gutil.ComparatorString)
t.Assert(array.IsEmpty(), true)
})
}
func TestSortedArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom([]interface{}{1, 2, 3, 4, 5}, gutil.ComparatorString)
copyArray := array.DeepCopy().(*garray.SortedArray)
array.Add(6)
copyArray.Add(7)
cval, _ := copyArray.Get(5)
val, _ := array.Get(5)
t.AssertNE(cval, val)
})
}

View File

@ -19,6 +19,26 @@ import (
"github.com/gogf/gf/v2/util/gconv"
)
func TestNewSortedIntArrayComparator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1, 4, 5, 6}
array1 := garray.NewSortedIntArrayComparator(func(a, b int) int {
return a - b
}, true)
array1.Append(a1...)
t.Assert(array1.Len(), 7)
t.Assert(array1.Interfaces(), []int{0, 1, 2, 3, 4, 5, 6})
})
}
func TestNewSortedIntArrayRange(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array1 := garray.NewSortedIntArrayRange(1, 5, 1)
t.Assert(array1.Len(), 5)
t.Assert(array1.Interfaces(), []int{1, 2, 3, 4, 5})
})
}
func TestNewSortedIntArrayFrom(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1, 4, 5, 6}
@ -37,6 +57,17 @@ func TestNewSortedIntArrayFromCopy(t *testing.T) {
})
}
func TestSortedIntArray_At(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1}
array1 := garray.NewSortedIntArrayFrom(a1)
v := array1.At(1)
t.Assert(v, 1)
})
}
func TestSortedIntArray_SetArray(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3}
@ -78,6 +109,10 @@ func TestSortedIntArray_Get(t *testing.T) {
v, ok = array1.Get(3)
t.Assert(v, 5)
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, 0)
t.Assert(ok, false)
})
}
@ -294,6 +329,9 @@ func TestSortedIntArray_Join(t *testing.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
t.Assert(array1.Join("."), `1.3.5`)
array2 := garray.NewSortedIntArrayFrom([]int{})
t.Assert(array2.Join("."), "")
})
}
@ -302,6 +340,9 @@ func TestSortedIntArray_String(t *testing.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
t.Assert(array1.String(), `[1,3,5]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -406,6 +447,11 @@ func TestSortedIntArray_Rand(t *testing.T) {
ns1, ok := array1.Rand()
t.AssertIN(ns1, a1)
t.Assert(ok, true)
array2 := garray.NewSortedIntArrayFrom([]int{})
ns2, ok := array2.Rand()
t.Assert(ns2, 0)
t.Assert(ok, false)
})
}
@ -419,6 +465,10 @@ func TestSortedIntArray_Rands(t *testing.T) {
ns2 := array1.Rands(6)
t.Assert(len(ns2), 6)
array2 := garray.NewSortedIntArrayFrom([]int{})
val := array2.Rands(1)
t.Assert(val, nil)
})
}
@ -450,6 +500,10 @@ func TestSortedIntArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 5)
t.Assert(array1, []int{1, 2, 3, 4, 5})
array2 := garray.NewSortedIntArrayFrom([]int{})
array2.Unique()
t.Assert(array2.Len(), 0)
})
}
@ -731,3 +785,22 @@ func TestSortedIntArray_Walk(t *testing.T) {
}), g.Slice{11, 12})
})
}
func TestSortedIntArray_IsEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom([]int{})
t.Assert(array.IsEmpty(), true)
})
}
func TestSortedIntArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom([]int{1, 2, 3, 4, 5})
copyArray := array.DeepCopy().(*garray.SortedIntArray)
array.Add(6)
copyArray.Add(7)
cval, _ := copyArray.Get(5)
val, _ := array.Get(5)
t.AssertNE(cval, val)
})
}

View File

@ -9,6 +9,7 @@
package garray_test
import (
"github.com/gogf/gf/v2/text/gstr"
"testing"
"time"
@ -19,6 +20,18 @@ import (
"github.com/gogf/gf/v2/util/gconv"
)
func TestNewSortedStrArrayComparator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
s1 := garray.NewSortedStrArrayComparator(func(a, b string) int {
return gstr.Compare(a, b)
})
s1.Add(a1...)
t.Assert(s1.Len(), 4)
t.Assert(s1, []string{"a", "b", "c", "d"})
})
}
func TestNewSortedStrArrayFrom(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
@ -58,6 +71,9 @@ func TestSortedStrArray_ContainsI(t *testing.T) {
t.Assert(s.Contains("A"), false)
t.Assert(s.Contains("a"), true)
t.Assert(s.ContainsI("A"), true)
s = garray.NewSortedStrArray()
t.Assert(s.Contains("A"), false)
})
}
@ -85,6 +101,10 @@ func TestSortedStrArray_Get(t *testing.T) {
v, ok = array1.Get(0)
t.Assert(v, "a")
t.Assert(ok, true)
v, ok = array1.Get(99)
t.Assert(v, "")
t.Assert(ok, false)
})
}
@ -361,6 +381,11 @@ func TestSortedStrArray_Rand(t *testing.T) {
v, ok := array1.Rand()
t.AssertIN(v, []string{"e", "a", "d"})
t.Assert(ok, true)
array2 := garray.NewSortedStrArrayFrom([]string{})
v, ok = array2.Rand()
t.Assert(v, "")
t.Assert(ok, false)
})
}
@ -375,6 +400,10 @@ func TestSortedStrArray_Rands(t *testing.T) {
s1 = array1.Rands(4)
t.Assert(len(s1), 4)
array2 := garray.NewSortedStrArrayFrom([]string{})
val := array2.Rands(1)
t.Assert(val, nil)
})
}
@ -391,6 +420,11 @@ func TestSortedStrArray_Join(t *testing.T) {
array1 := garray.NewSortedStrArrayFrom(a1)
t.Assert(array1.Join("."), `"b".\c.a`)
})
gtest.C(t, func(t *gtest.T) {
array1 := garray.NewSortedStrArrayFrom([]string{})
t.Assert(array1.Join("."), "")
})
}
func TestSortedStrArray_String(t *testing.T) {
@ -398,6 +432,9 @@ func TestSortedStrArray_String(t *testing.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
t.Assert(array1.String(), `["a","d","e"]`)
array1 = nil
t.Assert(array1.String(), "")
})
}
@ -469,6 +506,11 @@ func TestSortedStrArray_Unique(t *testing.T) {
array1.Unique()
t.Assert(array1.Len(), 3)
t.Assert(array1, []string{"1", "2", "3"})
array2 := garray.NewSortedStrArrayFrom([]string{})
array2.Unique()
t.Assert(array2.Len(), 0)
t.Assert(array2, []string{})
})
}
@ -755,3 +797,15 @@ func TestSortedStrArray_Walk(t *testing.T) {
}), g.Slice{"key-1", "key-2"})
})
}
func TestSortedStrArray_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom([]string{"a", "b", "c", "d"})
copyArray := array.DeepCopy().(*garray.SortedStrArray)
array.Add("e")
copyArray.Add("f")
cval, _ := copyArray.Get(4)
val, _ := array.Get(4)
t.AssertNE(cval, val)
})
}

View File

@ -12,6 +12,7 @@ import (
"bytes"
"container/list"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
"github.com/gogf/gf/v2/util/gconv"
@ -546,3 +547,23 @@ func (l *List) UnmarshalValue(value interface{}) (err error) {
l.PushBacks(array)
return err
}
// DeepCopy implements interface for deep copy of current type.
func (l *List) DeepCopy() interface{} {
l.mu.RLock()
defer l.mu.RUnlock()
if l.list == nil {
return nil
}
var (
length = l.list.Len()
values = make([]interface{}, length)
)
if length > 0 {
for i, e := 0, l.list.Front(); i < length; i, e = i+1, e.Next() {
values[i] = deepcopy.Copy(e.Value)
}
}
return NewFrom(values, l.mu.IsSafe())
}

View File

@ -755,3 +755,13 @@ func TestList_UnmarshalValue(t *testing.T) {
t.Assert(tlist.List.FrontAll(), []interface{}{1, 2, 3})
})
}
func TestList_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`})
copyList := l.DeepCopy()
cl := copyList.(*List)
cl.PopBack()
t.AssertNE(l.Size(), cl.Size())
})
}

View File

@ -8,6 +8,7 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -72,7 +73,7 @@ func (m *AnyAnyMap) Map() map[interface{}]interface{} {
return data
}
// MapCopy returns a copy of the underlying data of the hash map.
// MapCopy returns a shallow copy of the underlying data of the hash map.
func (m *AnyAnyMap) MapCopy() map[interface{}]interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
@ -497,3 +498,14 @@ func (m *AnyAnyMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *AnyAnyMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[interface{}]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewFrom(data, m.mu.IsSafe())
}

View File

@ -9,6 +9,7 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -499,3 +500,14 @@ func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntAnyMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewIntAnyMapFrom(data, m.mu.IsSafe())
}

View File

@ -470,3 +470,14 @@ func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntIntMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]int, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewIntIntMapFrom(data, m.mu.IsSafe())
}

View File

@ -470,3 +470,14 @@ func (m *IntStrMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *IntStrMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[int]string, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewIntStrMapFrom(data, m.mu.IsSafe())
}

View File

@ -9,6 +9,7 @@ package gmap
import (
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -485,3 +486,14 @@ func (m *StrAnyMap) UnmarshalValue(value interface{}) (err error) {
m.data = gconv.Map(value)
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrAnyMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]interface{}, len(m.data))
for k, v := range m.data {
data[k] = deepcopy.Copy(v)
}
return NewStrAnyMapFrom(data, m.mu.IsSafe())
}

View File

@ -474,3 +474,14 @@ func (m *StrIntMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrIntMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]int, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewStrIntMapFrom(data, m.mu.IsSafe())
}

View File

@ -463,3 +463,14 @@ func (m *StrStrMap) UnmarshalValue(value interface{}) (err error) {
m.data = gconv.MapStrStr(value)
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *StrStrMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[string]string, len(m.data))
for k, v := range m.data {
data[k] = v
}
return NewStrStrMapFrom(data, m.mu.IsSafe())
}

View File

@ -12,6 +12,7 @@ import (
"github.com/gogf/gf/v2/container/glist"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/internal/rwmutex"
@ -590,3 +591,19 @@ func (m *ListMap) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (m *ListMap) DeepCopy() interface{} {
m.mu.RLock()
defer m.mu.RUnlock()
data := make(map[interface{}]interface{}, len(m.data))
if m.list != nil {
var node *gListMapNode
m.list.IteratorAsc(func(e *glist.Element) bool {
node = e.Value.(*gListMapNode)
data[node.key] = deepcopy.Copy(node.value)
return true
})
}
return NewListMapFrom(data, m.mu.IsSafe())
}

View File

@ -602,8 +602,12 @@ func ExampleAnyAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.Map = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleAnyAnyMap_MarshalJSON() {

View File

@ -601,8 +601,12 @@ func ExampleIntAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.IntAnyMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"1":"v1"}
// 0
}
func ExampleIntAnyMap_MarshalJSON() {

View File

@ -529,8 +529,12 @@ func ExampleIntIntMap_String() {
fmt.Println(m.String())
var m1 *gmap.IntIntMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"1":1}
// 0
}
func ExampleIntIntMap_MarshalJSON() {

View File

@ -599,8 +599,12 @@ func ExampleStrAnyMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrAnyMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleStrAnyMap_MarshalJSON() {

View File

@ -8,11 +8,10 @@ package gmap_test
import (
"fmt"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/container/gmap"
)
func ExampleStrIntMap_Iterator() {
@ -535,8 +534,12 @@ func ExampleStrIntMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrIntMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":1}
// 0
}
func ExampleStrIntMap_MarshalJSON() {

View File

@ -531,8 +531,12 @@ func ExampleStrStrMap_String() {
fmt.Println(m.String())
var m1 *gmap.StrStrMap = nil
fmt.Println(len(m1.String()))
// Output:
// {"k1":"v1"}
// 0
}
func ExampleStrStrMap_MarshalJSON() {

View File

@ -90,7 +90,7 @@ func ExampleNewFrom() {
}
func ExampleNewHashMap() {
m := gmap.New()
m := gmap.NewHashMap()
m.Set("key1", "val1")
fmt.Println(m)
@ -105,7 +105,7 @@ func ExampleNewHashMapFrom() {
m.Set("key1", "val1")
fmt.Println(m)
n := gmap.NewFrom(m.MapCopy(), true)
n := gmap.NewHashMapFrom(m.MapCopy(), true)
fmt.Println(n)
// Output:

View File

@ -171,6 +171,9 @@ func Test_AnyAnyMap_Merge(t *testing.T) {
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
m3 := gmap.NewAnyAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -296,6 +299,10 @@ func Test_AnyAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.AssertNil(k3)
t.AssertNil(v3)
})
}
@ -327,6 +334,11 @@ func Test_AnyAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -365,3 +377,17 @@ func TestAnyAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_AnyAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.AnyAnyMap)
n.Set("k1", "val1")
t.AssertNE(m.Get("k1"), n.Get("k1"))
})
}

View File

@ -82,6 +82,12 @@ func Test_IntAnyMap_Basic(t *testing.T) {
m2 := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: "2"})
t.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap(true)
m.Set(1, 1)
t.Assert(m.Map(), map[int]interface{}{1: 1})
})
}
func Test_IntAnyMap_Set_Fun(t *testing.T) {
@ -171,6 +177,9 @@ func Test_IntAnyMap_Merge(t *testing.T) {
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]interface{}{1: 1, 2: "2"})
m3 := gmap.NewIntAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -271,6 +280,10 @@ func Test_IntAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.AssertNil(v3)
})
}
@ -302,6 +315,11 @@ func Test_IntAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -340,3 +358,17 @@ func TestIntAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "v2")
})
}
func Test_IntAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
1: "v1",
2: "v2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntAnyMap)
n.Set(1, "val1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -86,6 +86,12 @@ func Test_IntIntMap_Basic(t *testing.T) {
m2 := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2})
t.Assert(m2.Map(), map[int]int{1: 1, 2: 2})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap(true)
m.Set(1, 1)
t.Assert(m.Map(), map[int]int{1: 1})
})
}
func Test_IntIntMap_Set_Fun(t *testing.T) {
@ -102,6 +108,11 @@ func Test_IntIntMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock(2, getInt), false)
t.Assert(m.SetIfNotExistFuncLock(4, getInt), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(nil)
t.Assert(m.GetOrSetFuncLock(1, getInt), getInt())
})
}
func Test_IntIntMap_Batch(t *testing.T) {
@ -177,6 +188,9 @@ func Test_IntIntMap_Merge(t *testing.T) {
m2.Set(2, 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[int]int{1: 1, 2: 2})
m3 := gmap.NewIntIntMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -277,6 +291,10 @@ func Test_IntIntMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.Assert(v3, 0)
})
}
@ -308,6 +326,11 @@ func Test_IntIntMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -346,3 +369,17 @@ func TestIntIntMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "2")
})
}
func Test_IntIntMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(g.MapIntInt{
1: 1,
2: 2,
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntIntMap)
n.Set(1, 2)
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -63,6 +63,7 @@ func Test_IntStrMap_Basic(t *testing.T) {
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
t.Assert(m.GetOrSet(1, "a"), "a")
t.Assert(m.GetOrSet(2, "b"), "b")
t.Assert(m.SetIfNotExist(2, "b"), false)
@ -90,6 +91,29 @@ func Test_IntStrMap_Basic(t *testing.T) {
m2 := gmap.NewIntStrMapFrom(map[int]string{1: "a", 2: "b"})
t.Assert(m2.Map(), map[int]string{1: "a", 2: "b"})
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap(true)
m.Set(1, "val1")
t.Assert(m.Map(), map[int]string{1: "val1"})
})
}
func TestIntStrMap_MapStrAny(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
t.Assert(m.MapStrAny(), g.MapStrAny{"1": "z", "2": "z"})
})
}
func TestIntStrMap_Sets(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
m.Sets(g.MapIntStr{1: "z", 2: "z"})
t.Assert(len(m.Map()), 2)
})
}
func Test_IntStrMap_Set_Fun(t *testing.T) {
@ -97,6 +121,8 @@ func Test_IntStrMap_Set_Fun(t *testing.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
t.Assert(m.GetOrSetFunc(1, getStr), "z")
t.Assert(m.GetOrSetFuncLock(2, getStr), "z")
t.Assert(m.Get(1), "z")
t.Assert(m.Get(2), "z")
t.Assert(m.SetIfNotExistFunc(1, getStr), false)
@ -105,6 +131,16 @@ func Test_IntStrMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock(2, getStr), false)
t.Assert(m.SetIfNotExistFuncLock(4, getStr), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
t.Assert(m.GetOrSetFuncLock(1, getStr), "z")
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(nil)
t.Assert(m.SetIfNotExistFuncLock(1, getStr), true)
})
}
func Test_IntStrMap_Batch(t *testing.T) {
@ -176,6 +212,10 @@ func Test_IntStrMap_Merge(t *testing.T) {
m2.Set(2, "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]string{1: "a", 2: "b"})
m3 := gmap.NewIntStrMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -275,6 +315,10 @@ func Test_IntStrMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, 0)
t.Assert(v3, "")
})
}
@ -306,6 +350,11 @@ func Test_IntStrMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -344,3 +393,55 @@ func TestIntStrMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get(2), "v2")
})
}
func TestIntStrMap_Replace(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
3: "v3",
})
t.Assert(m.Get(1), "v1")
t.Assert(m.Get(2), "v2")
t.Assert(m.Get(3), "v3")
m.Replace(g.MapIntStr{
1: "v2",
2: "v3",
3: "v1",
})
t.Assert(m.Get(1), "v2")
t.Assert(m.Get(2), "v3")
t.Assert(m.Get(3), "v1")
})
}
func TestIntStrMap_String(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
3: "v3",
})
t.Assert(m.String(), "{\"1\":\"v1\",\"2\":\"v2\",\"3\":\"v3\"}")
m = nil
t.Assert(len(m.String()), 0)
})
}
func Test_IntStrMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "val1",
2: "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.IntStrMap)
n.Set(1, "v1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -169,6 +169,10 @@ func Test_StrAnyMap_Merge(t *testing.T) {
m2.Set("b", "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]interface{}{"a": 1, "b": "2"})
m3 := gmap.NewStrAnyMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -283,6 +287,10 @@ func Test_StrAnyMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, "")
})
}
@ -314,6 +322,11 @@ func Test_StrAnyMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -352,3 +365,17 @@ func TestStrAnyMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_StrAnyMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
"key1": "val1",
"key2": "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrAnyMap)
n.Set("key1", "v1")
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -100,6 +100,11 @@ func Test_StrIntMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock("b", getInt), false)
t.Assert(m.SetIfNotExistFuncLock("d", getInt), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(nil)
t.Assert(m.GetOrSetFuncLock("a", getInt), 123)
})
}
func Test_StrIntMap_Batch(t *testing.T) {
@ -173,6 +178,9 @@ func Test_StrIntMap_Merge(t *testing.T) {
m2.Set("b", 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[string]int{"a": 1, "b": 2})
m3 := gmap.NewStrIntMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -287,6 +295,10 @@ func Test_StrIntMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, 0)
})
}
@ -318,6 +330,11 @@ func Test_StrIntMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -356,3 +373,17 @@ func TestStrIntMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), 2)
})
}
func Test_StrIntMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(g.MapStrInt{
"key1": 1,
"key2": 2,
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrIntMap)
n.Set("key1", 2)
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -98,6 +98,12 @@ func Test_StrStrMap_Set_Fun(t *testing.T) {
t.Assert(m.SetIfNotExistFuncLock("b", getStr), false)
t.Assert(m.SetIfNotExistFuncLock("d", getStr), true)
})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(nil)
t.Assert(m.GetOrSetFuncLock("b", getStr), "z")
})
}
func Test_StrStrMap_Batch(t *testing.T) {
@ -170,6 +176,9 @@ func Test_StrStrMap_Merge(t *testing.T) {
m2.Set("b", "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]string{"a": "a", "b": "b"})
m3 := gmap.NewStrStrMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -284,6 +293,10 @@ func Test_StrStrMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.Assert(k3, "")
t.Assert(v3, "")
})
}
@ -315,6 +328,11 @@ func Test_StrStrMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -353,3 +371,17 @@ func TestStrStrMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("k2"), "v2")
})
}
func Test_StrStrMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(g.MapStrStr{
"key1": "val1",
"key2": "val2",
})
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.StrStrMap)
n.Set("key1", "v1")
t.AssertNE(m.Get("key1"), n.Get("key1"))
})
}

View File

@ -154,6 +154,9 @@ func Test_ListMap_Basic_Merge(t *testing.T) {
m2.Set("key2", "val2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
m3 := gmap.NewListMapFrom(nil)
m3.Merge(m2)
t.Assert(m3.Map(), m2.Map())
})
}
@ -266,6 +269,10 @@ func Test_ListMap_Pop(t *testing.T) {
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
k3, v3 := m.Pop()
t.AssertNil(k3)
t.AssertNil(v3)
})
}
@ -297,6 +304,11 @@ func Test_ListMap_Pops(t *testing.T) {
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
v := m.Pops(1)
t.AssertNil(v)
v = m.Pops(-1)
t.AssertNil(v)
})
}
@ -335,3 +347,44 @@ func TestListMap_UnmarshalValue(t *testing.T) {
t.Assert(v.Map.Get("2"), "v2")
})
}
func TestListMap_String(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
t.Assert(m.String(), "{\"1\":\"\",\"2\":\"2\"}")
m1 := gmap.NewListMapFrom(nil)
t.Assert(m1.String(), "{}")
})
}
func TestListMap_MarshalJSON(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
res, err := m.MarshalJSON()
t.Assert(res, []byte("{\"1\":\"\",\"2\":\"2\"}"))
t.AssertNil(err)
m1 := gmap.NewListMapFrom(nil)
res, err = m1.MarshalJSON()
t.Assert(res, []byte("{}"))
t.AssertNil(err)
})
}
func TestListMap_DeepCopy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "1")
m.Set(2, "2")
t.Assert(m.Size(), 2)
n := m.DeepCopy().(*gmap.ListMap)
n.Set(1, "val1")
t.AssertNE(m.Get(1), n.Get(1))
})
}

View File

@ -510,3 +510,14 @@ func (set *Set) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *Set) DeepCopy() interface{} {
set.mu.RLock()
defer set.mu.RUnlock()
data := make(map[interface{}]struct{}, len(set.data))
for k, v := range set.data {
data[k] = v
}
return NewFrom(data, set.mu.IsSafe())
}

View File

@ -469,3 +469,18 @@ func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *IntSet) DeepCopy() interface{} {
set.mu.RLock()
defer set.mu.RUnlock()
var (
slice = make([]int, len(set.data))
index = 0
)
for k := range set.data {
slice[index] = k
index++
}
return NewIntSetFrom(slice, set.mu.IsSafe())
}

View File

@ -499,3 +499,18 @@ func (set *StrSet) UnmarshalValue(value interface{}) (err error) {
}
return
}
// DeepCopy implements interface for deep copy of current type.
func (set *StrSet) DeepCopy() interface{} {
set.mu.RLock()
defer set.mu.RUnlock()
var (
slice = make([]string, len(set.data))
index = 0
)
for k := range set.data {
slice[index] = k
index++
}
return NewStrSetFrom(slice, set.mu.IsSafe())
}

View File

@ -96,3 +96,8 @@ func (v *Bool) UnmarshalValue(value interface{}) error {
v.Set(gconv.Bool(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Bool) DeepCopy() interface{} {
return NewBool(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Byte) UnmarshalValue(value interface{}) error {
v.Set(gconv.Byte(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Byte) DeepCopy() interface{} {
return NewByte(v.Val())
}

View File

@ -30,7 +30,7 @@ func NewBytes(value ...[]byte) *Bytes {
return t
}
// Clone clones and returns a new concurrent-safe object for []byte type.
// Clone clones and returns a new shallow copy object for []byte type.
func (v *Bytes) Clone() *Bytes {
return NewBytes(v.Val())
}
@ -83,3 +83,11 @@ func (v *Bytes) UnmarshalValue(value interface{}) error {
v.Set(gconv.Bytes(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Bytes) DeepCopy() interface{} {
oldBytes := v.Val()
newBytes := make([]byte, len(oldBytes))
copy(newBytes, oldBytes)
return NewBytes(newBytes)
}

View File

@ -87,3 +87,8 @@ func (v *Float32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Float32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Float32) DeepCopy() interface{} {
return NewFloat32(v.Val())
}

View File

@ -87,3 +87,8 @@ func (v *Float64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Float64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Float64) DeepCopy() interface{} {
return NewFloat64(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Int) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int) DeepCopy() interface{} {
return NewInt(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Int32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int32) DeepCopy() interface{} {
return NewInt32(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Int64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Int64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Int64) DeepCopy() interface{} {
return NewInt64(v.Val())
}

View File

@ -9,6 +9,7 @@ package gtype
import (
"sync/atomic"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
)
@ -71,3 +72,8 @@ func (v *Interface) UnmarshalValue(value interface{}) error {
v.Set(value)
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Interface) DeepCopy() interface{} {
return NewInterface(deepcopy.Copy(v.Val()))
}

View File

@ -75,3 +75,8 @@ func (v *Uint) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint) DeepCopy() interface{} {
return NewUint(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Uint32) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint32(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint32) DeepCopy() interface{} {
return NewUint32(v.Val())
}

View File

@ -75,3 +75,8 @@ func (v *Uint64) UnmarshalValue(value interface{}) error {
v.Set(gconv.Uint64(value))
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Uint64) DeepCopy() interface{} {
return NewUint64(v.Val())
}

View File

@ -11,9 +11,11 @@ import (
"time"
"github.com/gogf/gf/v2/container/gtype"
"github.com/gogf/gf/v2/internal/deepcopy"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gutil"
)
// Var is an universal variable type implementer.
@ -37,6 +39,11 @@ func New(value interface{}, safe ...bool) *Var {
}
}
// Copy does a deep copy of current Var and returns a pointer to this Var.
func (v *Var) Copy() *Var {
return New(gutil.Copy(v.Val()), v.safe)
}
// Clone does a shallow copy of current Var and returns a pointer to this Var.
func (v *Var) Clone() *Var {
return New(v.Val(), v.safe)
@ -188,3 +195,8 @@ func (v *Var) UnmarshalValue(value interface{}) error {
v.Set(value)
return nil
}
// DeepCopy implements interface for deep copy of current type.
func (v *Var) DeepCopy() interface{} {
return New(deepcopy.Copy(v.Val()), v.safe)
}

View File

@ -13,6 +13,7 @@ import (
"time"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gconv"
)
@ -303,3 +304,27 @@ func Test_UnmarshalValue(t *testing.T) {
t.Assert(v.Var.String(), "v")
})
}
func Test_Copy(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
src := g.Map{
"k1": "v1",
"k2": "v2",
}
srcVar := gvar.New(src)
dstVar := srcVar.Copy()
t.Assert(srcVar.Map(), src)
t.Assert(dstVar.Map(), src)
dstVar.Map()["k3"] = "v3"
t.Assert(srcVar.Map(), g.Map{
"k1": "v1",
"k2": "v2",
})
t.Assert(dstVar.Map(), g.Map{
"k1": "v1",
"k2": "v2",
"k3": "v3",
})
})
}

View File

@ -40,7 +40,7 @@ import _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
import _ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
```
Note:
- It does not support `Save/Replace` features.
- It does not support `Save` features.
## PostgreSQL
```
@ -75,8 +75,7 @@ Note:
- It does not support `InsertIgnore/InsertGetId` features.
- It does not support `Save/Replace` features.
- It does not support `Transaction` feature.
- It does not support `Transaction` feature.
- It does not support `RowsAffected` feature.
# Custom Drivers

View File

@ -10,19 +10,23 @@ package clickhouse
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"strings"
"github.com/ClickHouse/clickhouse-go"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/gogf/gf/v2/container/gmap"
"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/os/gctx"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/google/uuid"
"net/url"
"strings"
"time"
)
// Driver is the driver for postgresql database.
@ -32,13 +36,23 @@ type Driver struct {
var (
// tableFieldsMap caches the table information retrieved from database.
tableFieldsMap = gmap.New(true)
errUnsupportedInsertIgnore = errors.New("unsupported method: InsertIgnore")
errUnsupportedInsertGetId = errors.New("unsupported method: InsertGetId")
errUnsupportedReplace = errors.New("unsupported method: Replace")
errUnsupportedBegin = errors.New("unsupported method: Begin")
errUnsupportedTransaction = errors.New("unsupported method: Transaction")
errSQLNull = errors.New("SQL cannot be null")
tableFieldsMap = gmap.New(true)
errUnsupportedInsertIgnore = errors.New("unsupported method:InsertIgnore")
errUnsupportedInsertGetId = errors.New("unsupported method:InsertGetId")
errUnsupportedReplace = errors.New("unsupported method:Replace")
errUnsupportedBegin = errors.New("unsupported method:Begin")
errUnsupportedTransaction = errors.New("unsupported method:Transaction")
)
const (
updateFilterPattern = `(?i)UPDATE[\s]+?(\w+[\.]?\w+)[\s]+?SET`
deleteFilterPattern = `(?i)DELETE[\s]+?FROM[\s]+?(\w+[\.]?\w+)`
filterTypePattern = `(?i)^UPDATE|DELETE`
replaceSchemaPattern = `@(.+?)/([\w\.\-]+)+`
needParsedSqlInCtx gctx.StrKey = "NeedParsedSql"
OrmTagForStruct = "orm"
driverName = "clickhouse"
)
func init() {
@ -62,27 +76,28 @@ func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
// Open creates and returns an underlying sql.DB object for clickhouse.
func (d *Driver) Open(config *gdb.ConfigNode) (*sql.DB, error) {
var (
source string
driver = "clickhouse"
)
// clickhouse://username:password@host1:9000,host2:9000/database?dial_timeout=200ms&max_execution_time=60
if config.Link != "" {
source = config.Link
// Custom changing the schema in runtime.
if config.Name != "" {
source, _ = gregex.ReplaceString(`@(.+?)/([\w\.\-]+)+`, "@$1/"+config.Name, source)
config.Link, _ = gregex.ReplaceString(replaceSchemaPattern, "@$1/"+config.Name, config.Link)
} else {
// If no schema, the link is matched for replacement
dbName, _ := gregex.MatchString(replaceSchemaPattern, config.Link)
if len(dbName) > 0 {
config.Name = dbName[len(dbName)-1]
}
}
} else if config.Pass != "" {
source = fmt.Sprintf(
"clickhouse://%s:%s@%s:%s/%s?charset=%s&debug=%s",
config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset, gconv.String(config.Debug))
config.Link = fmt.Sprintf(
"clickhouse://%s:%s@%s:%s/%s?charset=%s&debug=%t",
config.User, url.PathEscape(config.Pass), config.Host, config.Port, config.Name, config.Charset, config.Debug)
} else {
source = fmt.Sprintf(
"clickhouse://%s@%s:%s/%s?charset=%s&debug=%s",
config.User, config.Host, config.Port, config.Name, config.Charset, gconv.String(config.Debug))
config.Link = fmt.Sprintf(
"clickhouse://%s@%s:%s/%s?charset=%s&debug=%t",
config.User, config.Host, config.Port, config.Name, config.Charset, config.Debug)
}
db, err := sql.Open(driver, source)
db, err := sql.Open(driverName, config.Link)
if err != nil {
return nil, err
}
@ -133,7 +148,7 @@ func (d *Driver) TableFields(
if link, err = d.SlaveLink(useSchema); err != nil {
return nil
}
getColumnsSql := fmt.Sprintf("select name,position,default_expression,comment from `system`.columns c where database = '%s' and `table` = '%s'", d.GetConfig().Name, table)
getColumnsSql := fmt.Sprintf("select name,position,default_expression,comment,type,is_in_partition_key,is_in_sorting_key,is_in_primary_key,is_in_sampling_key from `system`.columns c where database = '%s' and `table` = '%s'", d.GetConfig().Name, table)
result, err = d.DoSelect(ctx, link, getColumnsSql)
if err != nil {
return nil
@ -215,29 +230,55 @@ func (d *Driver) ping(conn *sql.DB) error {
func (d *Driver) DoFilter(
ctx context.Context, link gdb.Link, originSql string, args []interface{},
) (newSql string, newArgs []interface{}, err error) {
// It replaces STD SQL to Clickhouse SQL grammar.
// MySQL eg: UPDATE `table` SET xxx
// Clickhouse eg: ALTER TABLE `table` UPDATE xxx
// MySQL eg: DELETE FROM `table`
// Clickhouse eg: ALTER TABLE `table` DELETE WHERE filter_expr
result, err := gregex.MatchString("(?i)^UPDATE|DELETE", originSql)
if len(args) == 0 {
return originSql, args, nil
}
var index int
// Convert placeholder char '?' to string "$x".
originSql, _ = gregex.ReplaceStringFunc(`\?`, originSql, func(s string) string {
index++
return fmt.Sprintf(`$%d`, index)
})
// Only SQL generated through the framework is processed.
if !d.getNeedParsedSqlFromCtx(ctx) {
return originSql, args, nil
}
// replace STD SQL to Clickhouse SQL grammar
modeRes, err := gregex.MatchString(filterTypePattern, strings.TrimSpace(originSql))
if err != nil {
return "", nil, err
}
if len(result) != 0 {
sqlSlice := strings.Split(originSql, " ")
if len(sqlSlice) < 3 {
return "", nil, errSQLNull
if len(modeRes) == 0 {
return originSql, args, nil
}
// Only delete/ UPDATE statements require filter
switch strings.ToUpper(modeRes[0]) {
case "UPDATE":
// MySQL eg: UPDATE table_name SET field1=new-value1, field2=new-value2 [WHERE Clause]
// Clickhouse eg: ALTER TABLE [db.]table UPDATE column1 = expr1 [, ...] WHERE filter_expr
newSql, err = gregex.ReplaceStringFuncMatch(updateFilterPattern, originSql, func(s []string) string {
return fmt.Sprintf("ALTER TABLE %s UPDATE", s[1])
})
if err != nil {
return "", nil, err
}
ck := []string{"ALTER", "TABLE"}
switch strings.ToUpper(result[0]) {
case "UPDATE":
sqlSlice = append(append(append(ck, sqlSlice[1]), result[0]), sqlSlice[3:]...)
return strings.Join(sqlSlice, " "), args, nil
case "DELETE":
sqlSlice = append(append(append(ck, sqlSlice[2]), result[0]), sqlSlice[3:]...)
return strings.Join(sqlSlice, " "), args, nil
return newSql, args, nil
case "DELETE":
// MySQL eg: DELETE FROM table_name [WHERE Clause]
// Clickhouse eg: ALTER TABLE [db.]table [ON CLUSTER cluster] DELETE WHERE filter_expr
newSql, err = gregex.ReplaceStringFuncMatch(deleteFilterPattern, originSql, func(s []string) string {
return fmt.Sprintf("ALTER TABLE %s DELETE", s[1])
})
if err != nil {
return "", nil, err
}
return newSql, args, nil
}
return originSql, args, nil
}
@ -295,6 +336,82 @@ func (d *Driver) DoInsert(
return stdSqlResult, tx.Commit()
}
// ConvertDataForRecord converting for any data that will be inserted into table/collection as a record.
func (d *Driver) ConvertDataForRecord(ctx context.Context, value interface{}) (map[string]interface{}, error) {
m := gconv.Map(value, OrmTagForStruct)
// transforms a value of a particular type
for k, v := range m {
switch itemValue := v.(type) {
case time.Time:
m[k] = itemValue
// If the time is zero, it then updates it to nil,
// which will insert/update the value to database as "null".
if itemValue.IsZero() {
m[k] = nil
}
case uuid.UUID:
m[k] = itemValue
case *time.Time:
m[k] = itemValue
// If the time is zero, it then updates it to nil,
// which will insert/update the value to database as "null".
if itemValue == nil || itemValue.IsZero() {
m[k] = nil
}
case gtime.Time:
// for gtime type, needs to get time.Time
m[k] = itemValue.Time
// If the time is zero, it then updates it to nil,
// which will insert/update the value to database as "null".
if itemValue.IsZero() {
m[k] = nil
}
case *gtime.Time:
// for gtime type, needs to get time.Time
if itemValue != nil {
m[k] = itemValue.Time
}
// If the time is zero, it then updates it to nil,
// which will insert/update the value to database as "null".
if itemValue == nil || itemValue.IsZero() {
m[k] = nil
}
default:
// if the other type implements valuer for the driver package
// the converted result is used
// otherwise the interface data is committed
valuer, ok := itemValue.(driver.Valuer)
if !ok {
m[k] = itemValue
continue
}
convertedValue, err := valuer.Value()
if err != nil {
return nil, err
}
m[k] = convertedValue
}
}
return m, nil
}
func (d *Driver) DoDelete(ctx context.Context, link gdb.Link, table string, condition string, args ...interface{}) (result sql.Result, err error) {
ctx = d.injectNeedParsedSql(ctx)
return d.Core.DoDelete(ctx, link, table, condition, args...)
}
func (d *Driver) DoUpdate(ctx context.Context, link gdb.Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) {
ctx = d.injectNeedParsedSql(ctx)
return d.Core.DoUpdate(ctx, link, table, data, condition, args...)
}
// InsertIgnore Other queries for modifying data parts are not supported: REPLACE, MERGE, UPSERT, INSERT UPDATE.
func (d *Driver) InsertIgnore(ctx context.Context, table string, data interface{}, batch ...int) (sql.Result, error) {
return nil, errUnsupportedInsertIgnore
@ -317,3 +434,17 @@ func (d *Driver) Begin(ctx context.Context) (tx *gdb.TX, err error) {
func (d *Driver) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) error {
return errUnsupportedTransaction
}
func (d *Driver) injectNeedParsedSql(ctx context.Context) context.Context {
if ctx.Value(needParsedSqlInCtx) != nil {
return ctx
}
return context.WithValue(ctx, needParsedSqlInCtx, true)
}
func (d *Driver) getNeedParsedSqlFromCtx(ctx context.Context) bool {
if ctx.Value(needParsedSqlInCtx) != nil {
return true
}
return false
}

View File

@ -3,6 +3,10 @@ package clickhouse
import (
"context"
"fmt"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/guid"
"github.com/google/uuid"
"strings"
"testing"
"time"
@ -13,18 +17,103 @@ import (
"github.com/gogf/gf/v2/util/grand"
)
// table DDL
// CREATE TABLE visits
// (
// id UInt64,
// duration Float64,
// url String,
// created DateTime
//)
// ENGINE = MergeTree()
// PRIMARY KEY id
// ORDER BY id
func InitClickhouse() gdb.DB {
const (
sqlVisitsDDL = `
CREATE TABLE IF NOT EXISTS visits (
id UInt64,
duration Float64,
url String,
created DateTime
) ENGINE = MergeTree()
PRIMARY KEY id
ORDER BY id
`
dimSqlDDL = `
CREATE TABLE IF NOT EXISTS dim (
"code" String COMMENT '编码',
"translation" String COMMENT '译文',
"superior" UInt64 COMMENT '上级ID',
"row_number" UInt16 COMMENT '行号',
"is_active" UInt8 COMMENT '是否激活',
"is_preset" UInt8 COMMENT '是否预置',
"category" String COMMENT '类别',
"tree_path" Array(String) COMMENT '树路径',
"id" UInt64 COMMENT '代理主键ID',
"scd" UInt64 COMMENT '缓慢变化维ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位',
"created_by" UInt64 COMMENT '创建者ID',
"created_at" DateTime64(3,'Asia/Shanghai') COMMENT '创建时间',
"updated_by" UInt64 COMMENT '最后修改者ID',
"updated_at" DateTime64(3,'Asia/Shanghai') COMMENT '最后修改时间',
"updated_tick" UInt16 COMMENT '累计修改次数'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("id","scd")
COMMENT '会计准则';
`
dimSqlDML = `
insert into dim (code, translation, superior, row_number, is_active, is_preset, category, tree_path, id, scd, version, sign, created_by, created_at, updated_by, updated_at, updated_tick)
values ('CN', '{"zh_CN":"中国大陆会计准则","en_US":"Chinese mainland accounting legislation"}', 0, 1, 1, 1, 1, '[''CN'']', 607972403489804288, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0),
('HK', '{"zh_CN":"中国香港会计准则","en_US":"Chinese Hong Kong accounting legislation"}', 0, 2, 1, 1, 1, '[''HK'']', 607972558544834566, 0, 0, 0, 607536279118155777, '2017-09-06 00:00:00', 607536279118155777, '2017-09-06 00:00:00', 0);
`
factSqlDDL = `
CREATE TABLE IF NOT EXISTS fact (
"adjustment_level" UInt64 COMMENT '调整层ID',
"data_version" UInt64 COMMENT '数据版本ID',
"accounting_legislation" UInt64 COMMENT '会计准则ID',
"fiscal_year" UInt16 COMMENT '会计年度',
"fiscal_period" UInt8 COMMENT '会计期间',
"fiscal_year_period" UInt32 COMMENT '会计年度期间',
"legal_entity" UInt64 COMMENT '法人主体ID',
"cost_center" UInt64 COMMENT '成本中心ID',
"legal_entity_partner" UInt64 COMMENT '内部关联方ID',
"financial_posting" UInt64 COMMENT '凭证头ID',
"line" UInt16 COMMENT '行号',
"general_ledger_account" UInt64 COMMENT '总账科目ID',
"debit" Decimal64(9) COMMENT '借方金额',
"credit" Decimal64(9) COMMENT '贷方金额',
"transaction_currency" UInt64 COMMENT '交易币种ID',
"debit_tc" Decimal64(9) COMMENT '借方金额(交易币种)',
"credit_tc" Decimal64(9) COMMENT '贷方金额(交易币种)',
"posting_date" Date32 COMMENT '过账日期',
"gc_year" UInt16 COMMENT '公历年',
"gc_quarter" UInt8 COMMENT '公历季',
"gc_month" UInt8 COMMENT '公历月',
"gc_week" UInt8 COMMENT '公历周',
"raw_info" String COMMENT '源信息',
"summary" String COMMENT '摘要',
"id" UInt64 COMMENT '代理主键ID',
"version" UInt64 COMMENT 'Merge版本ID',
"sign" Int8 COMMENT '标识位'
) ENGINE = ReplacingMergeTree("version")
ORDER BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period","financial_posting","line")
PARTITION BY ("adjustment_level","data_version","legal_entity","fiscal_year","fiscal_period")
COMMENT '数据主表';
`
factSqlDML = `
insert into fact (adjustment_level, data_version, accounting_legislation, fiscal_year, fiscal_period, fiscal_year_period, legal_entity, cost_center, legal_entity_partner, financial_posting, line, general_ledger_account, debit, credit, transaction_currency, debit_tc, credit_tc, posting_date, gc_year, gc_quarter, gc_month, gc_week, raw_info, summary, id, version, sign)
values (607970943242866688, 607973669943119880, 607972403489804288, 2022, 3, 202203, 607974511316307985, 0, 607976190010986520, 607996702456025136, 1, 607985607569838111, 8674.39, 0, 607974898261823505, 8674.39, 0, '2022-03-05', 2022, 1, 3, 11, '{}', '摘要', 607992882741121073, 0, 0),
(607970943242866688, 607973669943119880, 607972403489804288, 2022, 4, 202204, 607974511316307985, 0, 607976190010986520, 607993586419503145, 1, 607985607569838111, 9999.88, 0, 607974898261823505, 9999.88, 0, '2022-04-10', 2022, 2, 4, 18, '{}', '摘要', 607996939140599857, 0, 0);
`
expmSqlDDL = `
CREATE TABLE IF NOT EXISTS data_type (
Col1 UInt8 COMMENT '列1'
, Col2 Nullable(String) COMMENT '列2'
, Col3 FixedString(3) COMMENT '列3'
, Col4 String COMMENT '列4'
, Col5 Map(String, UInt8) COMMENT '列5'
, Col6 Array(String) COMMENT '列6'
, Col7 Tuple(String, UInt8, Array(Map(String, String))) COMMENT '列7'
, Col8 DateTime COMMENT '列8'
, Col9 UUID COMMENT '列9'
, Col10 DateTime COMMENT '列10'
) ENGINE = MergeTree()
PRIMARY KEY Col4
ORDER BY Col4
`
)
func clickhouseConfigDB() gdb.DB {
connect, err := gdb.New(gdb.ConfigNode{
Host: "127.0.0.1",
Port: "9000",
@ -38,135 +127,150 @@ func InitClickhouse() gdb.DB {
return connect
}
func TestDriverClickhouse_Create(t *testing.T) {
gtest.AssertNil(createClickhouseTable(InitClickhouse()))
}
func createClickhouseTable(connect gdb.DB) error {
sqlStr := "CREATE TABLE IF NOT EXISTS visits (id UInt64,duration Float64,url String,created DateTime) ENGINE = MergeTree() PRIMARY KEY id ORDER BY id"
_, err := connect.Exec(context.Background(), sqlStr)
func createClickhouseTableVisits(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), sqlVisitsDDL)
return err
}
func dropClickhouseTable(conn gdb.DB) {
func createClickhouseTableDim(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), dimSqlDDL)
return err
}
func createClickhouseTableFact(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), factSqlDDL)
return err
}
func createClickhouseExampleTable(connect gdb.DB) error {
_, err := connect.Exec(context.Background(), expmSqlDDL)
return err
}
func dropClickhouseTableVisits(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `visits`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseTableDim(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `dim`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseTableFact(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `fact`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func dropClickhouseExampleTable(conn gdb.DB) {
sqlStr := fmt.Sprintf("DROP TABLE IF EXISTS `data_type`")
_, _ = conn.Exec(context.Background(), sqlStr)
}
func TestDriverClickhouse_Create(t *testing.T) {
gtest.AssertNil(createClickhouseTableVisits(clickhouseConfigDB()))
}
func TestDriverClickhouse_New(t *testing.T) {
connect := InitClickhouse()
connect := clickhouseConfigDB()
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
gtest.AssertNil(connect.PingSlave())
}
func TestDriverClickhouse_OpenLink_Ping(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
}
func TestDriverClickhouse_Tables(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
tables, err := connect.Tables(context.Background())
gtest.AssertNil(err)
gtest.AssertNE(len(tables), 0)
}
func TestDriverClickhouse_TableFields_Use_Config(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
field, err := connect.TableFields(context.Background(), "visits")
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
}
func TestDriverClickhouse_TableFields_Use_Link(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
field, err := connect.TableFields(context.Background(), "visits")
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
}
func TestDriverClickhouse_Transaction(t *testing.T) {
connect := InitClickhouse()
defer dropClickhouseTable(connect)
connect := clickhouseConfigDB()
defer dropClickhouseTableVisits(connect)
gtest.AssertNE(connect.Transaction(context.Background(), func(ctx context.Context, tx *gdb.TX) error {
return nil
}), nil)
}
func TestDriverClickhouse_DoDelete(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
_, err := connect.Model("visits").Where("created >", "2021-01-01 00:00:00").Delete()
gtest.AssertNil(err)
}
func TestDriverClickhouse_DoUpdate(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
_, err := connect.Model("visits").Where("created > ", "2021-01-01 15:15:15").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNil(err)
_, err = connect.Model("visits").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNE(err, nil)
_, err = connect.Model("visits").Update()
gtest.AssertNE(err, nil)
}
func TestDriverClickhouse_Select(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
data, err := connect.Model("visits").All()
gtest.AssertNil(err)
gtest.AssertEQ(len(data), 0)
}
func TestDriver_InsertIgnore(t *testing.T) {
connect := InitClickhouse()
func TestDriverClickhouse_InsertIgnore(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.InsertIgnore(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedInsertIgnore)
}
func TestDriver_InsertAndGetId(t *testing.T) {
connect := InitClickhouse()
func TestDriverClickhouse_InsertAndGetId(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.InsertAndGetId(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedInsertGetId)
}
func TestDriver_Replace(t *testing.T) {
connect := InitClickhouse()
_, err := connect.Replace(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedReplace)
}
func TestDriverClickhouse_DoInsertOne(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
func TestDriverClickhouse_InsertOne(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Data(g.Map{
"id": grand.Intn(999),
"duration": float64(grand.Intn(999)),
"url": gconv.String(grand.Intn(999)),
"created": time.Now().Format("2006-01-02 15:04:05"),
"created": time.Now(),
}).Insert()
gtest.AssertNil(err)
}
func TestDriver_DoInsertMany(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
defer dropClickhouseTable(connect)
func TestDriverClickhouse_InsertMany(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
tx, err := connect.Begin(context.Background())
gtest.AssertEQ(err, errUnsupportedBegin)
gtest.AssertNil(tx)
}
func TestDriverClickhouse_DoInsert(t *testing.T) {
connect := InitClickhouse()
gtest.AssertEQ(createClickhouseTable(connect), nil)
func TestDriverClickhouse_Insert(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
type insertItem struct {
Id int `orm:"id"`
Duration float64 `orm:"duration"`
Url string `orm:"url"`
Created string `orm:"created"`
Id uint64 `orm:"id"`
Duration float64 `orm:"duration"`
Url string `orm:"url"`
Created time.Time `orm:"created"`
}
var (
insertUrl = "https://goframe.org"
total = 0
item = insertItem{
Id: 0,
Duration: 1,
Url: insertUrl,
Created: time.Now().Format("2006-01-02 15:04:05"),
Created: time.Now(),
}
)
_, err := connect.Model("visits").Data(item).Insert()
@ -176,13 +280,12 @@ func TestDriverClickhouse_DoInsert(t *testing.T) {
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 2)
list := []*insertItem{}
var list []*insertItem
for i := 0; i < 50; i++ {
list = append(list, &insertItem{
Id: grand.Intn(999),
Duration: float64(grand.Intn(999)),
Url: insertUrl,
Created: time.Now().Format("2006-01-02 15:04:05"),
Created: time.Now(),
})
}
_, err = connect.Model("visits").Data(list).Insert()
@ -192,63 +295,248 @@ func TestDriverClickhouse_DoInsert(t *testing.T) {
total, err = connect.Model("visits").Count()
gtest.AssertNil(err)
gtest.AssertEQ(total, 102)
dropClickhouseTable(connect)
}
func TestDriverClickhouse_DoExec(t *testing.T) {
connect := InitClickhouse()
gtest.AssertNil(createClickhouseTable(connect))
defer dropClickhouseTable(connect)
func TestDriverClickhouse_Insert_Use_Exec(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableFact(connect), nil)
defer dropClickhouseTableFact(connect)
_, err := connect.Exec(context.Background(), factSqlDML)
gtest.AssertNil(err)
}
func TestDriverClickhouse_Delete(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Where("created >", "2021-01-01 00:00:00").Delete()
gtest.AssertNil(err)
_, err = connect.Model("visits").
Where("created >", "2021-01-01 00:00:00").
Where("duration > ", 0).
Where("url is not null").
Delete()
gtest.AssertNil(err)
}
func TestDriverClickhouse_Update(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableVisits(connect), nil)
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Where("created > ", "2021-01-01 15:15:15").Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
gtest.AssertNil(err)
_, err = connect.Model("visits").
Where("created > ", "2021-01-01 15:15:15").
Where("duration > ", 0).
Where("url is not null").
Data(g.Map{
"created": time.Now().Format("2006-01-02 15:04:05"),
}).Update()
}
func TestDriverClickhouse_Replace(t *testing.T) {
connect := clickhouseConfigDB()
_, err := connect.Replace(context.Background(), "", nil)
gtest.AssertEQ(err, errUnsupportedReplace)
}
func TestDriverClickhouse_DoFilter(t *testing.T) {
rawSQL := "select * from visits where 1 = 1"
this := Driver{}
replaceSQL, _, err := this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(rawSQL, replaceSQL)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
rawSQL = "update visit set url = '1'"
replaceSQL, _, err = this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
rawSQL = "delete from visit"
replaceSQL, _, err = this.DoFilter(context.Background(), nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
ctx := this.injectNeedParsedSql(context.Background())
rawSQL = "UPDATE visit SET url = '1' WHERE url = '0'"
replaceSQL, _, err = this.DoFilter(ctx, nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit UPDATE url = '1' WHERE url = '0'")
rawSQL = "DELETE FROM visit WHERE url = '0'"
replaceSQL, _, err = this.DoFilter(ctx, nil, rawSQL, []interface{}{1})
gtest.AssertNil(err)
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit DELETE WHERE url = '0'")
}
func TestDriverClickhouse_Select(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
_, err := connect.Model("visits").Data(g.Map{
"url": "goframe.org",
"duration": float64(1),
}).Insert()
gtest.AssertNil(err)
temp, err := connect.Model("visits").Where("url", "goframe.org").Where("duration >= ", 1).One()
gtest.AssertNil(err)
gtest.AssertEQ(temp.IsEmpty(), false)
_, err = connect.Model("visits").Data(g.Map{
"url": "goframe.org",
"duration": float64(2),
}).Insert()
gtest.AssertNil(err)
data, err := connect.Model("visits").Where("url", "goframe.org").Where("duration >= ", 1).All()
gtest.AssertNil(err)
gtest.AssertEQ(len(data), 2)
}
func TestDriverClickhouse_Exec_OPTIMIZE(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseTableVisits(connect))
defer dropClickhouseTableVisits(connect)
sqlStr := "OPTIMIZE table visits"
_, err := connect.Exec(context.Background(), sqlStr)
gtest.AssertNil(err)
}
func TestDriver_DoFilter(t *testing.T) {
rawSQL := "select * from visits where 1 = 1"
this := Driver{}
replaceSQL, _, err := this.DoFilter(nil, nil, rawSQL, nil)
func TestDriverClickhouse_ExecInsert(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertEQ(createClickhouseTableDim(connect), nil)
defer dropClickhouseTableDim(connect)
_, err := connect.Exec(context.Background(), dimSqlDML)
gtest.AssertNil(err)
gtest.AssertEQ(rawSQL, replaceSQL)
rawSQL = "update visit set url = '1'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit update url = '1'")
rawSQL = "delete from visit"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit delete")
rawSQL = "update visit set url = '1' where url = '0'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit update url = '1' where url = '0'")
rawSQL = "delete from visit where url='0'"
replaceSQL, _, err = this.DoFilter(nil, nil, rawSQL, nil)
gtest.AssertNil(err)
// this SQL can't run ,clickhouse will report an error because there is no WHERE statement
gtest.AssertEQ(replaceSQL, "ALTER TABLE visit delete where url='0'")
}
func TestDriver_TableFields(t *testing.T) {
connect := InitClickhouse()
gtest.AssertNil(createClickhouseTable(connect))
defer dropClickhouseTable(connect)
field, err := connect.TableFields(context.Background(), "visits")
func TestDriverClickhouse_NilTime(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseExampleTable(connect))
defer dropClickhouseExampleTable(connect)
type testNilTime struct {
Col1 uint8
Col2 string
Col3 string
Col4 string
Col5 map[string]uint8
Col6 []string
Col7 []interface{}
Col8 *time.Time
Col9 uuid.UUID
Col10 *gtime.Time
}
insertData := []*testNilTime{}
for i := 0; i < 10000; i++ {
insertData = append(insertData, &testNilTime{
Col4: "Inc.",
Col9: uuid.New(),
Col7: []interface{}{ // Tuple(String, UInt8, Array(Map(String, String)))
"String Value", uint8(5), []map[string]string{
map[string]string{"key": "value"},
map[string]string{"key": "value"},
map[string]string{"key": "value"},
}},
})
}
_, err := connect.Model("data_type").Data(insertData).Insert()
gtest.AssertNil(err)
gtest.AssertEQ(len(field), 4)
gtest.AssertNQ(field, nil)
count, err := connect.Model("data_type").Where("Col4", "Inc.").Count()
gtest.AssertNil(err)
gtest.AssertEQ(count, 10000)
}
func TestDriver_OpenLink(t *testing.T) {
connect, err := gdb.New(gdb.ConfigNode{
Link: "clickhouse://default@127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60&skip_verify=true&secure=false&compress=true",
func TestDriverClickhouse_BatchInsert(t *testing.T) {
// example from
// https://github.com/ClickHouse/clickhouse-go/blob/v2/examples/std/batch/main.go
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseExampleTable(connect))
defer dropClickhouseExampleTable(connect)
insertData := []g.Map{}
for i := 0; i < 10000; i++ {
insertData = append(insertData, g.Map{
"Col1": uint8(42),
"Col2": "ClickHouse",
"Col3": "Inc",
"Col4": guid.S(),
"Col5": map[string]uint8{"key": 1}, // Map(String, UInt8)
"Col6": []string{"Q", "W", "E", "R", "T", "Y"}, // Array(String)
"Col7": []interface{}{ // Tuple(String, UInt8, Array(Map(String, String)))
"String Value", uint8(5), []map[string]string{
map[string]string{"key": "value"},
map[string]string{"key": "value"},
map[string]string{"key": "value"},
},
},
"Col8": gtime.Now(),
"Col9": uuid.New(),
"Col10": nil,
})
}
_, err := connect.Model("data_type").Data(insertData).Insert()
gtest.AssertNil(err)
count, err := connect.Model("data_type").Where("Col2", "ClickHouse").Where("Col3", "Inc").Count()
gtest.AssertNil(err)
gtest.AssertEQ(count, 10000)
}
func TestDriverClickhouse_Open(t *testing.T) {
// link
// DSM
// clickhouse://username:password@host1:9000,host2:9000/database?dial_timeout=200ms&max_execution_time=60
link := "clickhouse://default@127.0.0.1:9000,127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60"
db, err := gdb.New(gdb.ConfigNode{
Link: link,
Type: "clickhouse",
})
gtest.AssertNil(err)
gtest.AssertNE(connect, nil)
gtest.AssertNil(connect.PingMaster())
gtest.AssertNil(db.PingMaster())
}
func TestDriverClickhouse_ReplaceConfig(t *testing.T) {
db := &Driver{}
// parse link's name set to config
c1 := &gdb.ConfigNode{}
c1.Link = "clickhouse://default@127.0.0.1:9000,127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60"
_, _ = db.Open(c1)
gtest.AssertEQ(c1.Name, "default")
// replace link's name from config
c2 := &gdb.ConfigNode{}
c2.Name = "clickhouseJohn"
c2.Link = "clickhouse://default@127.0.0.1:9000,127.0.0.1:9000/default?dial_timeout=200ms&max_execution_time=60"
_, _ = db.Open(c2)
gtest.AssertEQ(strings.Contains(c2.Link, "clickhouseJohn"), true)
}
func TestDriverClickhouse_TableFields(t *testing.T) {
connect := clickhouseConfigDB()
gtest.AssertNil(createClickhouseExampleTable(connect))
defer dropClickhouseExampleTable(connect)
dataTypeTable, err := connect.TableFields(context.Background(), "data_type")
gtest.AssertNil(err)
gtest.AssertNE(dataTypeTable, nil)
var result = map[string][]interface{}{
"Col1": {1, "Col1", "UInt8", false, "", "", "", "列1"},
"Col2": {2, "Col2", "String", true, "", "", "", "列2"},
"Col3": {3, "Col3", "FixedString(3)", false, "", "", "", "列3"},
"Col4": {4, "Col4", "String", false, "", "", "", "列4"},
"Col5": {5, "Col5", "Map(String, UInt8)", false, "", "", "", "列5"},
"Col6": {6, "Col6", "Array(String)", false, "", "", "", "列6"},
"Col7": {7, "Col7", "Tuple(String, UInt8, Array(Map(String, String)))", false, "", "", "", "列7"},
"Col8": {8, "Col8", "DateTime", false, "", "", "", "列8"},
"Col9": {9, "Col9", "UUID", false, "", "", "", "列9"},
"Col10": {10, "Col10", "DateTime", false, "", "", "", "列10"},
}
for k, v := range result {
_, ok := dataTypeTable[k]
gtest.AssertEQ(ok, true)
gtest.AssertEQ(dataTypeTable[k].Index, v[0])
gtest.AssertEQ(dataTypeTable[k].Name, v[1])
gtest.AssertEQ(dataTypeTable[k].Type, v[2])
gtest.AssertEQ(dataTypeTable[k].Null, v[3])
gtest.AssertEQ(dataTypeTable[k].Key, v[4])
gtest.AssertEQ(dataTypeTable[k].Default, v[5])
gtest.AssertEQ(dataTypeTable[k].Comment, v[7])
}
}

View File

@ -3,8 +3,12 @@ module github.com/gogf/gf/contrib/drivers/clickhouse/v2
go 1.15
require (
github.com/ClickHouse/clickhouse-go v1.5.2
github.com/ClickHouse/clickhouse-go/v2 v2.0.15
github.com/gogf/gf/v2 v2.0.0
github.com/google/uuid v1.3.0
)
replace github.com/gogf/gf/v2 => ../../../
replace (
github.com/ClickHouse/clickhouse-go/v2 => github.com/gogf/clickhouse-go/v2 v2.0.15-compatible
github.com/gogf/gf/v2 => ../../../
)

View File

@ -1,14 +1,16 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/ClickHouse/clickhouse-go v1.5.2 h1:yXgaOZ8WEHrd+okvZXjzulSt1zS33nM4ujfx9lVncl8=
github.com/ClickHouse/clickhouse-go v1.5.2/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/ClickHouse/clickhouse-go v1.5.4 h1:cKjXeYLNWVJIx2J1K6H2CqyRmfwVJVY1OV1coaaFcI0=
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -26,10 +28,15 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogf/clickhouse-go/v2 v2.0.15-compatible h1:VYgibtmI/u+hUQmtJpC7zzg1YJsDCXS052R7vCqGpDc=
github.com/gogf/clickhouse-go/v2 v2.0.15-compatible/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -44,15 +51,22 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@ -64,6 +78,7 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@ -71,23 +86,43 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
@ -97,11 +132,13 @@ go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48
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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
@ -110,14 +147,18 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -128,8 +169,11 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 h1:Js08h5hqB5xyWR789+QqueR6sDE8mk+YvpETZ+F6X9Y=
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -138,7 +182,9 @@ golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObF
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -152,8 +198,9 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@ -165,5 +212,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -22,8 +25,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
@ -41,14 +44,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
@ -65,12 +69,16 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -111,6 +119,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -121,6 +130,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -13,14 +13,14 @@
package mssql
import (
_ "github.com/denisenkom/go-mssqldb"
"context"
"database/sql"
"fmt"
"strconv"
"strings"
_ "github.com/denisenkom/go-mssqldb"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
@ -299,6 +299,7 @@ ORDER BY a.id,a.colorder`,
}
fields = make(map[string]*gdb.TableField)
for i, m := range result {
fields[m["Field"].String()] = &gdb.TableField{
Index: i,
Name: m["Field"].String(),

View File

@ -0,0 +1,144 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). 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 mssql_test
import (
"context"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
)
var (
db gdb.DB
dblink gdb.DB
dbErr gdb.DB
ctx context.Context
)
const (
TableSize = 10
TableName = "t_user"
TestSchema1 = "test1"
TestSchema2 = "test2"
TableNamePrefix1 = "gf_"
TestDbUser = "sa"
TestDbPass = "LoremIpsum86"
CreateTime = "2018-10-24 10:00:00"
)
func init() {
node := gdb.ConfigNode{
Host: "127.0.0.1",
Port: "1433",
User: TestDbUser,
Pass: TestDbPass,
Name: "test",
Type: "mssql",
Role: "master",
Charset: "utf8",
Weight: 1,
MaxIdleConnCount: 10,
MaxOpenConnCount: 10,
}
nodeLink := gdb.ConfigNode{
Type: "mssql",
Name: "test",
Link: fmt.Sprintf("user id=%s;password=%s;server=%s;port=%s;database=%s;encrypt=disable",
node.User, node.Pass, node.Host, node.Port, node.Name),
}
nodeErr := gdb.ConfigNode{
Type: "mssql",
Link: fmt.Sprintf("user id=%s;password=%s;server=%s;port=%s;database=%s;encrypt=disable",
node.User, "node.Pass", node.Host, node.Port, node.Name),
}
gdb.AddConfigNode(gdb.DefaultGroupName, node)
if r, err := gdb.New(node); err != nil {
gtest.Fatal(err)
} else {
db = r
}
gdb.AddConfigNode("dblink", nodeLink)
if r, err := gdb.New(nodeLink); err != nil {
gtest.Fatal(err)
} else {
dblink = r
}
gdb.AddConfigNode("dbErr", nodeErr)
if r, err := gdb.New(nodeErr); err != nil {
gtest.Fatal(err)
} else {
dbErr = r
}
ctx = context.Background()
}
func createTable(table ...string) (name string) {
if len(table) > 0 {
name = table[0]
} else {
name = fmt.Sprintf("user_%d", gtime.Timestamp())
}
dropTable(name)
if _, err := db.Exec(context.Background(), fmt.Sprintf(`
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='%s' and xtype='U')
CREATE TABLE %s (
ID numeric(10,0) NOT NULL,
PASSPORT VARCHAR(45) NULL,
PASSWORD VARCHAR(32) NULL,
NICKNAME VARCHAR(45) NULL,
CREATE_TIME datetime NULL,
PRIMARY KEY (ID))
`, name, name)); err != nil {
gtest.Fatal(err)
}
db.Schema("test")
return
}
func createInitTable(table ...string) (name string) {
name = createTable(table...)
array := garray.New(true)
for i := 1; i <= TableSize; i++ {
array.Append(g.Map{
"id": i,
"passport": fmt.Sprintf(`user_%d`, i),
"password": fmt.Sprintf(`pass_%d`, i),
"nickname": fmt.Sprintf(`name_%d`, i),
"create_time": gtime.Now().String(),
})
}
result, err := db.Insert(context.Background(), name, array.Slice())
gtest.Assert(err, nil)
n, e := result.RowsAffected()
gtest.Assert(e, nil)
gtest.Assert(n, TableSize)
return
}
func dropTable(table string) {
if _, err := db.Exec(context.Background(), fmt.Sprintf(`
IF EXISTS (SELECT * FROM sysobjects WHERE name='%s' and xtype='U')
DROP TABLE %s
`, table, table)); err != nil {
gtest.Fatal(err)
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -20,8 +23,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
@ -39,14 +42,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
@ -63,12 +67,16 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -107,6 +115,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -117,6 +126,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -13,6 +13,9 @@ import (
"fmt"
"net/url"
_ "github.com/go-sql-driver/mysql"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gcode"
@ -32,8 +35,15 @@ var (
)
func init() {
if err := gdb.Register(`mysql`, New()); err != nil {
panic(err)
var (
err error
driverObj = New()
driverNames = g.SliceStr{"mysql", "mariadb", "tidb"}
)
for _, driverName := range driverNames {
if err = gdb.Register(driverName, driverObj); err != nil {
panic(err)
}
}
}

View File

@ -37,10 +37,10 @@ func Test_Func_ConvertDataForRecord(t *testing.T) {
}
gtest.C(t, func(t *gtest.T) {
c := &gdb.Core{}
m := c.ConvertDataForRecord(nil, new(Test))
m, err := c.ConvertDataForRecord(nil, new(Test))
t.AssertNil(err)
t.Assert(len(m), 1)
t.AssertNE(m["reset_password_token_at"], nil)
t.Assert(m["reset_password_token_at"], new(mysql.NullTime))
t.Assert(m["reset_password_token_at"], nil)
})
}

View File

@ -82,3 +82,27 @@ func Test_Model_InnerJoinOnField(t *testing.T) {
t.Assert(r[1]["id"], "2")
})
}
func Test_Model_FieldsPrefix(t *testing.T) {
var (
table1 = gtime.TimestampNanoStr() + "_table1"
table2 = gtime.TimestampNanoStr() + "_table2"
)
createInitTable(table1)
defer dropTable(table1)
createInitTable(table2)
defer dropTable(table2)
gtest.C(t, func(t *gtest.T) {
r, err := db.Model(table1).
FieldsPrefix(table1, "id").
FieldsPrefix(table2, "nickname").
LeftJoinOnField(table2, "id").
WhereIn("id", g.Slice{1, 2}).
Order("id asc").All()
t.AssertNil(err)
t.Assert(len(r), 2)
t.Assert(r[0]["id"], "1")
t.Assert(r[0]["nickname"], "name_1")
})
}

View File

@ -1,10 +1,36 @@
module github.com/gogf/gf/contrib/drivers/oracle/v2
go 1.15
go 1.17
require (
github.com/gogf/gf/v2 v2.0.0
github.com/mattn/go-oci8 v0.1.1
github.com/sijms/go-ora/v2 v2.4.20
)
require (
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)
replace github.com/gogf/gf/v2 => ../../../

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -20,8 +23,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@ -31,20 +34,20 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
@ -52,8 +55,6 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-oci8 v0.1.1 h1:aEUDxNAyDG0tv8CA3TArnDQNyc4EhnWlsfxRgDHABHM=
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
@ -63,14 +64,19 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sijms/go-ora/v2 v2.4.20 h1:9e3z7VLBQXRAHGiIda1GEFtRhfxata0LghyMZqvLKew=
github.com/sijms/go-ora/v2 v2.4.20/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
@ -107,6 +113,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -117,6 +124,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -132,7 +140,6 @@ golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -141,7 +148,6 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -5,7 +5,7 @@
// You can obtain one at https://github.com/gogf/gf.
//
// Note:
// 1. It needs manually import: _ "github.com/mattn/go-oci8"
// 1. It needs manually import: _ "github.com/sijms/go-ora/v2"
// 2. It does not support Save/Replace features.
// 3. It does not support LastInsertId.
@ -13,15 +13,10 @@
package oracle
import (
_ "github.com/mattn/go-oci8"
"context"
"database/sql"
"fmt"
"reflect"
"strconv"
"strings"
"time"
gora "github.com/sijms/go-ora/v2"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
@ -30,6 +25,8 @@ import (
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"strconv"
"strings"
)
// Driver is the driver for oracle database.
@ -65,9 +62,18 @@ func (d *Driver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
var (
source string
underlyingDriverName = "oci8"
underlyingDriverName = "oracle"
)
// [username/[password]@]host[:port][/service_name][?param1=value1&...&paramN=valueN]
options := map[string]string{
"CONNECTION TIMEOUT": "60",
"PREFETCH_ROWS": "25",
}
if config.Debug {
options["TRACE FILE"] = "oracle_trace.log"
}
// [username:[password]@]host[:port][/service_name][?param1=value1&...&paramN=valueN]
if config.Link != "" {
source = config.Link
// Custom changing the schema in runtime.
@ -75,10 +81,7 @@ func (d *Driver) Open(config *gdb.ConfigNode) (db *sql.DB, err error) {
source, _ = gregex.ReplaceString(`@(.+?)/([\w\.\-]+)+`, "@$1/"+config.Name, source)
}
} else {
source = fmt.Sprintf(
"%s/%s@%s:%s/%s",
config.User, config.Pass, config.Host, config.Port, config.Name,
)
source = gora.BuildUrl(config.Host, gconv.Int(config.Port), config.Name, config.User, config.Pass, options)
}
if db, err = sql.Open(underlyingDriverName, source); err != nil {
@ -99,8 +102,8 @@ func (d *Driver) FilteredLink() string {
return ""
}
s, _ := gregex.ReplaceString(
`(.+?)\s*/\s*(.+)\s*@\s*(.+)\s*:\s*(\d+)\s*/\s*(.+)`,
`$1/xxx@$3:$4/$5`,
`(.+?)\s*:\s*(.+)\s*@\s*(.+)\s*:\s*(\d+)\s*/\s*(.+)`,
`$1:xxx@$3:$4/$5`,
linkInfo,
)
return s
@ -124,16 +127,7 @@ func (d *Driver) DoFilter(ctx context.Context, link gdb.Link, sql string, args [
return fmt.Sprintf(":v%d", index)
})
newSql, _ = gregex.ReplaceString("\"", "", newSql)
// Handle string datetime argument.
for i, v := range args {
if reflect.TypeOf(v).Kind() == reflect.String {
valueStr := gconv.String(v)
if gregex.IsMatchString(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$`, valueStr) {
// args[i] = fmt.Sprintf(`TO_DATE('%s','yyyy-MM-dd HH:MI:SS')`, valueStr)
args[i], _ = time.ParseInLocation("2006-01-02 15:04:05", valueStr, time.Local)
}
}
}
newSql = d.parseSql(newSql)
newArgs = args
return
@ -168,7 +162,7 @@ func (d *Driver) parseSql(sql string) string {
strings.EqualFold(queryExpr[3], "LIMIT") == false {
break
}
first, limit := 0, 0
page, limit := 0, 0
for i := 1; i < len(allMatch[index]); i++ {
if len(strings.TrimSpace(allMatch[index][i])) == 0 {
continue
@ -176,8 +170,16 @@ func (d *Driver) parseSql(sql string) string {
if strings.HasPrefix(allMatch[index][i], "LIMIT") {
if allMatch[index][i+2] != "" {
first, _ = strconv.Atoi(allMatch[index][i+1])
page, _ = strconv.Atoi(allMatch[index][i+1])
limit, _ = strconv.Atoi(allMatch[index][i+2])
if page <= 0 {
page = 1
}
limit = (page/limit + 1) * limit
page, _ = strconv.Atoi(allMatch[index][i+1])
} else {
limit, _ = strconv.Atoi(allMatch[index][i+1])
}
@ -187,8 +189,8 @@ func (d *Driver) parseSql(sql string) string {
sql = fmt.Sprintf(
"SELECT * FROM "+
"(SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d)"+
" WHERE ROWNUM_ >= %d",
queryExpr[1], queryExpr[2], limit, first,
" WHERE ROWNUM_ > %d",
queryExpr[1], queryExpr[2], limit, page,
)
}
return sql
@ -241,7 +243,7 @@ SELECT
CASE DATA_TYPE
WHEN 'NUMBER' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
WHEN 'FLOAT' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
ELSE DATA_TYPE||'('||DATA_LENGTH||')' END AS TYPE
ELSE DATA_TYPE||'('||DATA_LENGTH||')' END AS TYPE,NULLABLE
FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '%s' ORDER BY COLUMN_ID`,
strings.ToUpper(table),
)
@ -256,10 +258,16 @@ FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '%s' ORDER BY COLUMN_ID`,
}
fields = make(map[string]*gdb.TableField)
for i, m := range result {
fields[strings.ToLower(m["FIELD"].String())] = &gdb.TableField{
isNull := false
if m["NULLABLE"].String() == "Y" {
isNull = true
}
fields[m["FIELD"].String()] = &gdb.TableField{
Index: i,
Name: strings.ToLower(m["FIELD"].String()),
Type: strings.ToLower(m["TYPE"].String()),
Name: m["FIELD"].String(),
Type: m["TYPE"].String(),
Null: isNull,
}
}
return fields
@ -288,10 +296,10 @@ func (d *Driver) DoInsert(
) (result sql.Result, err error) {
switch option.InsertOption {
case gdb.InsertOptionSave:
return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by mssql driver`)
return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by oracle driver`)
case gdb.InsertOptionReplace:
return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by mssql driver`)
return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by oracle driver`)
}
var (

View File

@ -0,0 +1,162 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). 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 oracle_test
import (
"context"
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
_ "github.com/sijms/go-ora/v2"
"strings"
)
var (
db gdb.DB
dblink gdb.DB
dbErr gdb.DB
ctx context.Context
)
const (
TableSize = 10
TableName = "t_user"
TestSchema1 = "test1"
TestSchema2 = "test2"
TableNamePrefix1 = "gf_"
TestSchema = "XE"
)
const (
TestDbIP = "127.0.0.1"
TestDbPort = "1521"
TestDbUser = "system"
TestDbPass = "oracle"
TestDbName = "XE"
TestDbType = "oracle"
)
func init() {
node := gdb.ConfigNode{
Host: TestDbIP,
Port: TestDbPort,
User: TestDbUser,
Pass: TestDbPass,
Name: TestDbName,
Type: TestDbType,
Role: "master",
Charset: "utf8",
Weight: 1,
MaxIdleConnCount: 10,
MaxOpenConnCount: 10,
}
nodeLink := gdb.ConfigNode{
Type: TestDbType,
Name: TestDbName,
Link: fmt.Sprintf("%s://%s:%s@%s:%s/%s",
TestDbType, TestDbUser, TestDbPass, TestDbIP, TestDbPort, TestDbName),
}
nodeErr := gdb.ConfigNode{
Host: TestDbIP,
Port: TestDbPort,
User: TestDbUser,
Pass: "1234",
Name: TestDbName,
Type: TestDbType,
Role: "master",
Charset: "utf8",
Weight: 1,
}
gdb.AddConfigNode(gdb.DefaultGroupName, node)
if r, err := gdb.New(node); err != nil {
gtest.Fatal(err)
} else {
db = r
}
gdb.AddConfigNode("dblink", nodeLink)
if r, err := gdb.New(nodeLink); err != nil {
gtest.Fatal(err)
} else {
dblink = r
}
gdb.AddConfigNode("dbErr", nodeErr)
if r, err := gdb.New(nodeErr); err != nil {
gtest.Fatal(err)
} else {
dbErr = r
}
ctx = context.Background()
}
func createTable(table ...string) (name string) {
if len(table) > 0 {
name = table[0]
} else {
name = fmt.Sprintf("user_%d", gtime.Timestamp())
}
dropTable(name)
if _, err := db.Exec(ctx, fmt.Sprintf(`
CREATE TABLE %s (
ID NUMBER(10) NOT NULL,
PASSPORT VARCHAR(45) NOT NULL,
PASSWORD CHAR(32) NOT NULL,
NICKNAME VARCHAR(45) NOT NULL,
CREATE_TIME varchar(45),
PRIMARY KEY (ID))
`, name)); err != nil {
gtest.Fatal(err)
}
//db.Schema("test")
return
}
func createInitTable(table ...string) (name string) {
name = createTable(table...)
array := garray.New(true)
for i := 1; i <= TableSize; i++ {
array.Append(g.Map{
"id": i,
"passport": fmt.Sprintf(`user_%d`, i),
"password": fmt.Sprintf(`pass_%d`, i),
"nickname": fmt.Sprintf(`name_%d`, i),
"create_time": gtime.Now().String(),
})
}
result, err := db.Insert(context.Background(), name, array.Slice())
gtest.Assert(err, nil)
n, e := result.RowsAffected()
gtest.Assert(e, nil)
gtest.Assert(n, TableSize)
return
}
func dropTable(table string) {
count, err := db.GetCount(ctx, "SELECT COUNT(*) FROM USER_TABLES WHERE TABLE_NAME = ?", strings.ToUpper(table))
if err != nil {
gtest.Fatal(err)
}
if count == 0 {
return
}
if _, err := db.Exec(ctx, fmt.Sprintf("DROP TABLE %s", table)); err != nil {
gtest.Fatal(err)
}
}

View File

@ -0,0 +1,665 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). 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 oracle_test
import (
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
"strings"
"testing"
)
func TestTables(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
tables := []string{"t_user1", "pop", "haha"}
for _, v := range tables {
createTable(v)
}
result, err := db.Tables(ctx)
gtest.Assert(err, nil)
for i := 0; i < len(tables); i++ {
find := false
for j := 0; j < len(result); j++ {
if strings.ToUpper(tables[i]) == result[j] {
find = true
break
}
}
gtest.AssertEQ(find, true)
}
result, err = db.Tables(ctx, TestSchema)
gtest.Assert(err, nil)
for i := 0; i < len(tables); i++ {
find := false
for j := 0; j < len(result); j++ {
if strings.ToUpper(tables[i]) == result[j] {
find = true
break
}
}
gtest.AssertEQ(find, true)
}
for _, v := range tables {
dropTable(v)
}
})
}
func TestTableFields(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
createTable("t_user")
defer dropTable("t_user")
var expect = map[string][]interface{}{
"ID": {"NUMBER(10,0)", false},
"PASSPORT": {"VARCHAR2(45)", false},
"PASSWORD": {"CHAR(32)", false},
"NICKNAME": {"VARCHAR2(45)", false},
"CREATE_TIME": {"VARCHAR2(45)", true},
}
_, err := dbErr.TableFields(ctx, "t_user")
gtest.AssertNE(err, nil)
res, err := db.TableFields(ctx, "t_user")
gtest.Assert(err, nil)
for k, v := range expect {
_, ok := res[k]
gtest.AssertEQ(ok, true)
gtest.AssertEQ(res[k].Name, k)
gtest.Assert(res[k].Type, v[0])
gtest.Assert(res[k].Null, v[1])
}
res, err = db.TableFields(ctx, "t_user", TestSchema)
gtest.Assert(err, nil)
for k, v := range expect {
_, ok := res[k]
gtest.AssertEQ(ok, true)
gtest.AssertEQ(res[k].Name, k)
gtest.Assert(res[k].Type, v[0])
gtest.Assert(res[k].Null, v[1])
}
})
gtest.C(t, func(t *gtest.T) {
_, err := db.TableFields(ctx, "t_user t_user2")
gtest.AssertNE(err, nil)
})
}
func TestFilteredLink(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
s := dblink.FilteredLink()
gtest.AssertEQ(s, "oracle:xxx@127.0.0.1:1521/XE")
})
}
func TestDoInsert(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
createTable("t_user")
defer dropTable("t_user")
i := 10
data := g.Map{
"ID": i,
"PASSPORT": fmt.Sprintf(`t%d`, i),
"PASSWORD": fmt.Sprintf(`p%d`, i),
"NICKNAME": fmt.Sprintf(`T%d`, i),
"CREATE_TIME": gtime.Now().String(),
}
_, err := db.Insert(ctx, "t_user", data)
gtest.Assert(err, nil)
})
gtest.C(t, func(t *gtest.T) {
createTable("t_user")
defer dropTable("t_user")
i := 10
data := g.Map{
"ID": i,
"PASSPORT": fmt.Sprintf(`t%d`, i),
"PASSWORD": fmt.Sprintf(`p%d`, i),
"NICKNAME": fmt.Sprintf(`T%d`, i),
"CREATE_TIME": gtime.Now().String(),
}
_, err := db.Save(ctx, "t_user", data, 10)
gtest.AssertNE(err, nil)
_, err = db.Replace(ctx, "t_user", data, 10)
gtest.AssertNE(err, nil)
})
}
func Test_DB_Ping(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err1 := db.PingMaster()
err2 := db.PingSlave()
t.Assert(err1, nil)
t.Assert(err2, nil)
})
}
func Test_DB_Query(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
_, err := db.Query(ctx, "SELECT ? from dual", 1)
t.AssertNil(err)
_, err = db.Query(ctx, "SELECT ?+? from dual", 1, 2)
t.AssertNil(err)
_, err = db.Query(ctx, "SELECT ?+? from dual", g.Slice{1, 2})
t.AssertNil(err)
_, err = db.Query(ctx, "ERROR")
t.AssertNE(err, nil)
})
}
func Test_DB_Exec(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
_, err := db.Exec(ctx, "SELECT ? from dual", 1)
t.AssertNil(err)
_, err = db.Exec(ctx, "ERROR")
t.AssertNE(err, nil)
})
}
func Test_DB_Insert(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
_, err := db.Insert(ctx, table, g.Map{
"ID": 1,
"PASSPORT": "t1",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "T1",
"CREATE_TIME": gtime.Now().String(),
})
t.AssertNil(err)
// normal map
result, err := db.Insert(ctx, table, g.Map{
"ID": "2",
"PASSPORT": "t2",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "name_2",
"CREATE_TIME": gtime.Now().String(),
})
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
// struct
type User struct {
Id int `gconv:"ID"`
Passport string `json:"PASSPORT"`
Password string `gconv:"PASSWORD"`
Nickname string `gconv:"NICKNAME"`
CreateTime string `json:"CREATE_TIME"`
}
timeStr := gtime.Now().String()
result, err = db.Insert(ctx, table, User{
Id: 3,
Passport: "user_3",
Password: "25d55ad283aa400af464c76d713c07ad",
Nickname: "name_3",
CreateTime: timeStr,
})
t.AssertNil(err)
n, _ = result.RowsAffected()
t.Assert(n, 1)
one, err := db.Model(table).Where("ID", 3).One()
t.AssertNil(err)
fmt.Println(one)
t.Assert(one["ID"].Int(), 3)
t.Assert(one["PASSPORT"].String(), "user_3")
t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d713c07ad")
t.Assert(one["NICKNAME"].String(), "name_3")
t.Assert(one["CREATE_TIME"].GTime().String(), timeStr)
// *struct
timeStr = gtime.Now().String()
result, err = db.Insert(ctx, table, &User{
Id: 4,
Passport: "t4",
Password: "25d55ad283aa400af464c76d713c07ad",
Nickname: "name_4",
CreateTime: timeStr,
})
t.AssertNil(err)
n, _ = result.RowsAffected()
t.Assert(n, 1)
one, err = db.Model(table).Where("ID", 4).One()
t.AssertNil(err)
t.Assert(one["ID"].Int(), 4)
t.Assert(one["PASSPORT"].String(), "t4")
t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d713c07ad")
t.Assert(one["NICKNAME"].String(), "name_4")
t.Assert(one["CREATE_TIME"].GTime().String(), timeStr)
// batch with Insert
timeStr = gtime.Now().String()
r, err := db.Insert(ctx, table, g.Slice{
g.Map{
"ID": 200,
"PASSPORT": "t200",
"PASSWORD": "25d55ad283aa400af464c76d71qw07ad",
"NICKNAME": "T200",
"CREATE_TIME": timeStr,
},
g.Map{
"ID": 300,
"PASSPORT": "t300",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "T300",
"CREATE_TIME": timeStr,
},
})
t.AssertNil(err)
n, _ = r.RowsAffected()
t.Assert(n, 2)
one, err = db.Model(table).Where("ID", 200).One()
t.AssertNil(err)
t.Assert(one["ID"].Int(), 200)
t.Assert(one["PASSPORT"].String(), "t200")
t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d71qw07ad")
t.Assert(one["NICKNAME"].String(), "T200")
t.Assert(one["CREATE_TIME"].GTime().String(), timeStr)
})
}
func Test_DB_BatchInsert(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
r, err := db.Insert(ctx, table, g.List{
{
"ID": 2,
"PASSPORT": "t2",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "name_2",
"CREATE_TIME": gtime.Now().String(),
},
{
"ID": 3,
"PASSPORT": "user_3",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "name_3",
"CREATE_TIME": gtime.Now().String(),
},
}, 1)
t.AssertNil(err)
n, _ := r.RowsAffected()
t.Assert(n, 2)
})
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
// []interface{}
r, err := db.Insert(ctx, table, g.Slice{
g.Map{
"ID": 2,
"PASSPORT": "t2",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "name_2",
"CREATE_TIME": gtime.Now().String(),
},
g.Map{
"ID": 3,
"PASSPORT": "user_3",
"PASSWORD": "25d55ad283aa400af464c76d713c07ad",
"NICKNAME": "name_3",
"CREATE_TIME": gtime.Now().String(),
},
}, 1)
t.AssertNil(err)
n, _ := r.RowsAffected()
t.Assert(n, 2)
})
// batch insert map
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
result, err := db.Insert(ctx, table, g.Map{
"ID": 1,
"PASSPORT": "t1",
"PASSWORD": "p1",
"NICKNAME": "T1",
"CREATE_TIME": gtime.Now().String(),
})
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
}
func Test_DB_BatchInsert_Struct(t *testing.T) {
// batch insert struct
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
type User struct {
Id int `c:"ID"`
Passport string `c:"PASSPORT"`
Password string `c:"PASSWORD"`
NickName string `c:"NICKNAME"`
CreateTime *gtime.Time `c:"CREATE_TIME"`
}
user := &User{
Id: 1,
Passport: "t1",
Password: "p1",
NickName: "T1",
CreateTime: gtime.Now(),
}
result, err := db.Insert(ctx, table, user)
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
})
}
func Test_DB_Update(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
result, err := db.Update(ctx, table, "password='987654321'", "id=3")
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)
one, err := db.Model(table).Where("ID", 3).One()
t.AssertNil(err)
t.Assert(one["ID"].Int(), 3)
t.Assert(one["PASSPORT"].String(), "user_3")
t.Assert(strings.TrimSpace(one["PASSWORD"].String()), "987654321")
t.Assert(one["NICKNAME"].String(), "name_3")
})
}
func Test_DB_GetAll(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 1)
t.AssertNil(err)
t.Assert(len(result), 1)
t.Assert(result[0]["ID"].Int(), 1)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), g.Slice{1})
t.AssertNil(err)
t.Assert(len(result), 1)
t.Assert(result[0]["ID"].Int(), 1)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id in(?)", table), g.Slice{1, 2, 3})
t.AssertNil(err)
t.Assert(len(result), 3)
t.Assert(result[0]["ID"].Int(), 1)
t.Assert(result[1]["ID"].Int(), 2)
t.Assert(result[2]["ID"].Int(), 3)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id in(?,?,?)", table), g.Slice{1, 2, 3})
t.AssertNil(err)
t.Assert(len(result), 3)
t.Assert(result[0]["ID"].Int(), 1)
t.Assert(result[1]["ID"].Int(), 2)
t.Assert(result[2]["ID"].Int(), 3)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id in(?,?,?)", table), g.Slice{1, 2, 3}...)
t.AssertNil(err)
t.Assert(len(result), 3)
t.Assert(result[0]["ID"].Int(), 1)
t.Assert(result[1]["ID"].Int(), 2)
t.Assert(result[2]["ID"].Int(), 3)
})
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf("SELECT * FROM %s WHERE id>=? AND id <=?", table), g.Slice{1, 3})
t.AssertNil(err)
t.Assert(len(result), 3)
t.Assert(result[0]["ID"].Int(), 1)
t.Assert(result[1]["ID"].Int(), 2)
t.Assert(result[2]["ID"].Int(), 3)
})
}
func Test_DB_GetOne(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
record, err := db.GetOne(ctx, fmt.Sprintf("SELECT * FROM %s WHERE passport=?", table), "user_1")
t.AssertNil(err)
t.Assert(record["NICKNAME"].String(), "name_1")
})
}
func Test_DB_GetValue(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
value, err := db.GetValue(ctx, fmt.Sprintf("SELECT id FROM %s WHERE passport=?", table), "user_3")
t.AssertNil(err)
t.Assert(value.Int(), 3)
})
}
func Test_DB_GetCount(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
count, err := db.GetCount(ctx, fmt.Sprintf("SELECT * FROM %s", table))
t.AssertNil(err)
t.Assert(count, TableSize)
})
}
func Test_DB_GetStruct(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.GetScan(ctx, user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3)
t.AssertNil(err)
t.Assert(user.NickName, "name_3")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
err := db.GetScan(ctx, user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3)
t.AssertNil(err)
t.Assert(user.NickName, "name_3")
})
}
func Test_DB_GetStructs(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
err := db.GetScan(ctx, &users, fmt.Sprintf("SELECT * FROM %s WHERE id>?", table), 1)
t.AssertNil(err)
t.Assert(len(users), TableSize-1)
t.Assert(users[0].Id, 2)
t.Assert(users[1].Id, 3)
t.Assert(users[2].Id, 4)
t.Assert(users[0].NickName, "name_2")
t.Assert(users[1].NickName, "name_3")
t.Assert(users[2].NickName, "name_4")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
err := db.GetScan(ctx, &users, fmt.Sprintf("SELECT * FROM %s WHERE id>?", table), 1)
t.AssertNil(err)
t.Assert(len(users), TableSize-1)
t.Assert(users[0].Id, 2)
t.Assert(users[1].Id, 3)
t.Assert(users[2].Id, 4)
t.Assert(users[0].NickName, "name_2")
t.Assert(users[1].NickName, "name_3")
t.Assert(users[2].NickName, "name_4")
})
}
func Test_DB_GetScan(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
user := new(User)
err := db.GetScan(ctx, user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3)
t.AssertNil(err)
t.Assert(user.NickName, "name_3")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var user *User
err := db.GetScan(ctx, &user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3)
t.AssertNil(err)
t.Assert(user.NickName, "name_3")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
user := new(User)
err := db.GetScan(ctx, user, fmt.Sprintf("SELECT * FROM %s WHERE id=?", table), 3)
t.AssertNil(err)
t.Assert(user.NickName, "name_3")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime gtime.Time
}
var users []User
err := db.GetScan(ctx, &users, fmt.Sprintf("SELECT * FROM %s WHERE id>?", table), 1)
t.AssertNil(err)
t.Assert(len(users), TableSize-1)
t.Assert(users[0].Id, 2)
t.Assert(users[1].Id, 3)
t.Assert(users[2].Id, 4)
t.Assert(users[0].NickName, "name_2")
t.Assert(users[1].NickName, "name_3")
t.Assert(users[2].NickName, "name_4")
})
gtest.C(t, func(t *gtest.T) {
type User struct {
Id int
Passport string
Password string
NickName string
CreateTime *gtime.Time
}
var users []User
err := db.GetScan(ctx, &users, fmt.Sprintf("SELECT * FROM %s WHERE id>?", table), 1)
t.AssertNil(err)
t.Assert(len(users), TableSize-1)
t.Assert(users[0].Id, 2)
t.Assert(users[1].Id, 3)
t.Assert(users[2].Id, 4)
t.Assert(users[0].NickName, "name_2")
t.Assert(users[1].NickName, "name_3")
t.Assert(users[2].NickName, "name_4")
})
}
func Test_DB_Delete(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
result, err := db.Delete(ctx, table, "1=1")
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, TableSize)
})
}
func Test_Empty_Slice_Argument(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
result, err := db.GetAll(ctx, fmt.Sprintf(`select * from %s where id in(?)`, table), g.Slice{})
t.AssertNil(err)
t.Assert(len(result), 0)
})
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -20,8 +23,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@ -37,14 +40,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
@ -63,12 +67,16 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -107,6 +115,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -117,6 +126,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -15,7 +15,6 @@ package pgsql
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
_ "github.com/lib/pq"
@ -212,7 +211,7 @@ ORDER BY a.attnum`,
Index: i,
Name: m["field"].String(),
Type: m["type"].String(),
Null: m["null"].Bool(),
Null: !m["null"].Bool(),
Key: m["key"].String(),
Default: m["default_value"].Val(),
Comment: m["comment"].String(),
@ -246,20 +245,3 @@ func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list
return d.Core.DoInsert(ctx, link, table, list, option)
}
}
// ConvertDataForRecord converting for any data that will be inserted into table/collection as a record.
func (d *Driver) ConvertDataForRecord(ctx context.Context, value interface{}) map[string]interface{} {
data := gdb.DataToMapDeep(value)
var err error
for k, v := range data {
if valuer, ok := v.(driver.Valuer); ok {
data[k], err = valuer.Value()
if err != nil {
return nil
}
} else {
data[k] = d.Core.ConvertDataForRecordValue(ctx, v)
}
}
return data
}

View File

@ -1,7 +1,10 @@
github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -20,8 +23,8 @@ github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.4 h1:kHoYkfZP6+pe04aFTnhDH6GDROa5yJdHJVNxV3F46Tg=
github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@ -37,14 +40,15 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
@ -63,12 +67,16 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -107,6 +115,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -117,6 +126,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -12,19 +12,20 @@
package sqlite
import (
_ "github.com/mattn/go-sqlite3"
"context"
"database/sql"
"fmt"
"strings"
_ "github.com/mattn/go-sqlite3"
"github.com/gogf/gf/v2/container/gmap"
"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/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)
// Driver is the driver for sqlite database.
@ -35,6 +36,8 @@ type Driver struct {
var (
// tableFieldsMap caches the table information retrieved from database.
tableFieldsMap = gmap.New(true)
// Error
ErrorSave = gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
)
func init() {
@ -147,10 +150,17 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string
}
fields = make(map[string]*gdb.TableField)
for i, m := range result {
mKey := ""
if m["pk"].Bool() {
mKey = "pri"
}
fields[strings.ToLower(m["name"].String())] = &gdb.TableField{
Index: i,
Name: strings.ToLower(m["name"].String()),
Type: strings.ToLower(m["type"].String()),
Index: i,
Name: strings.ToLower(m["name"].String()),
Type: strings.ToLower(m["type"].String()),
Key: mKey,
Default: m["dflt_value"].Val(),
Null: !m["notnull"].Bool(),
}
}
return fields
@ -166,11 +176,73 @@ func (d *Driver) TableFields(ctx context.Context, table string, schema ...string
func (d *Driver) DoInsert(ctx context.Context, link gdb.Link, table string, list gdb.List, option gdb.DoInsertOption) (result sql.Result, err error) {
switch option.InsertOption {
case gdb.InsertOptionSave:
return nil, gerror.NewCode(gcode.CodeNotSupported, `Save operation is not supported by sqlite driver`)
case gdb.InsertOptionReplace:
return nil, gerror.NewCode(gcode.CodeNotSupported, `Replace operation is not supported by sqlite driver`)
return nil, ErrorSave
case gdb.InsertOptionIgnore, gdb.InsertOptionReplace:
var (
keys []string // Field names.
values []string // Value holder string array, like: (?,?,?)
params []interface{} // Values that will be committed to underlying database driver.
onDuplicateStr string // onDuplicateStr is used in "ON DUPLICATE KEY UPDATE" statement.
)
// Handle the field names and placeholders.
for k := range list[0] {
keys = append(keys, k)
}
// Prepare the batch result pointer.
var (
charL, charR = d.GetChars()
batchResult = new(gdb.SqlResult)
keysStr = charL + strings.Join(keys, charR+","+charL) + charR
operation = "INSERT OR IGNORE"
)
if option.InsertOption == gdb.InsertOptionReplace {
operation = "INSERT OR REPLACE"
}
var (
listLength = len(list)
valueHolder = make([]string, 0)
)
for i := 0; i < listLength; i++ {
values = values[:0]
// Note that the map type is unordered,
// so it should use slice+key to retrieve the value.
for _, k := range keys {
if s, ok := list[i][k].(gdb.Raw); ok {
values = append(values, gconv.String(s))
} else {
values = append(values, "?")
params = append(params, list[i][k])
}
}
valueHolder = append(valueHolder, "("+gstr.Join(values, ",")+")")
// Batch package checks: It meets the batch number, or it is the last element.
if len(valueHolder) == option.BatchCount || (i == listLength-1 && len(valueHolder) > 0) {
var (
stdSqlResult sql.Result
affectedRows int64
)
stdSqlResult, err = d.DoExec(ctx, link, fmt.Sprintf(
"%s INTO %s(%s) VALUES%s %s",
operation, d.QuotePrefixTableName(table), keysStr,
gstr.Join(valueHolder, ","),
onDuplicateStr,
), params...)
if err != nil {
return stdSqlResult, err
}
if affectedRows, err = stdSqlResult.RowsAffected(); err != nil {
err = gerror.WrapCode(gcode.CodeDbOperationError, err, `sql.Result.RowsAffected failed`)
return stdSqlResult, err
} else {
batchResult.Result = stdSqlResult
batchResult.Affected += affectedRows
}
params = params[:0]
valueHolder = valueHolder[:0]
}
}
return batchResult, nil
default:
return d.Core.DoInsert(ctx, link, table, list, option)
}

View File

@ -0,0 +1,161 @@
// 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 sqlite_test
import (
"fmt"
"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"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/test/gtest"
)
var (
db gdb.DB
dbPrefix gdb.DB
dbInvalid gdb.DB
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 (
TableSize = 10
TableName = "user"
TestSchema1 = "test1"
TestSchema2 = "test2"
TableNamePrefix = "gf_"
CreateTime = "2018-10-24 10:00:00"
DBGroupTest = "test"
DBGroupPrefix = "prefix"
DBGroupInvalid = "invalid"
)
func init() {
fmt.Println("init sqlite db start")
if err := gfile.Mkdir(dbDir); err != nil {
gtest.Error(err)
}
fmt.Println("init sqlite db dir: ", dbDir)
configNode = gdb.ConfigNode{
Type: "sqlite",
Link: gfile.Join(dbDir, "test.db"),
Charset: "utf8",
}
nodePrefix := configNode
nodePrefix.Prefix = TableNamePrefix
nodeInvalid := configNode
gdb.AddConfigNode(DBGroupTest, configNode)
gdb.AddConfigNode(DBGroupPrefix, nodePrefix)
gdb.AddConfigNode(DBGroupInvalid, nodeInvalid)
gdb.AddConfigNode(gdb.DefaultGroupName, configNode)
// Default db.
if r, err := gdb.NewByGroup(); err != nil {
gtest.Error(err)
} else {
db = r
}
// Prefix db.
if r, err := gdb.NewByGroup(DBGroupPrefix); err != nil {
gtest.Error(err)
} else {
dbPrefix = r
}
// Invalid db.
if r, err := gdb.NewByGroup(DBGroupInvalid); err != nil {
gtest.Error(err)
} else {
dbInvalid = r
}
fmt.Println("init sqlite db finish")
}
func createTable(table ...string) string {
return createTableWithDb(db, table...)
}
func createInitTable(table ...string) string {
return createInitTableWithDb(db, table...)
}
func dropTable(table string) {
dropTableWithDb(db, table)
}
func createTableWithDb(db gdb.DB, table ...string) (name string) {
if len(table) > 0 {
name = table[0]
} else {
name = fmt.Sprintf(`%s_%d`, TableName, gtime.TimestampNano())
}
dropTableWithDb(db, name)
if _, err := db.Exec(ctx, fmt.Sprintf(`
CREATE TABLE %s (
id INTEGER PRIMARY KEY AUTOINCREMENT
UNIQUE
NOT NULL,
passport VARCHAR(45) NOT NULL
DEFAULT passport,
password VARCHAR(128) NOT NULL
DEFAULT password,
nickname VARCHAR(45),
create_time DATETIME
);
`, name,
)); err != nil {
gtest.Fatal(err)
}
return
}
func createInitTableWithDb(db gdb.DB, table ...string) (name string) {
name = createTableWithDb(db, table...)
array := garray.New(true)
for i := 1; i <= TableSize; i++ {
array.Append(g.Map{
"id": i,
"passport": fmt.Sprintf(`user_%d`, i),
"password": fmt.Sprintf(`pass_%d`, i),
"nickname": fmt.Sprintf(`name_%d`, i),
"create_time": gtime.NewFromStr(CreateTime).String(),
})
}
result, err := db.Insert(ctx, name, array.Slice())
gtest.AssertNil(err)
n, e := result.RowsAffected()
gtest.Assert(e, nil)
gtest.Assert(n, TableSize)
return
}
func dropTableWithDb(db gdb.DB, table string) {
if _, err := db.Exec(ctx, fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)); err != nil {
gtest.Error(err)
}
}

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