From 48435a3e2f1c7dc46f0deaab54e2e4d7e2b93aea Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Fri, 15 May 2026 17:43:12 +0800 Subject: [PATCH 01/10] Bump Go from 1.24 to 1.25 --- .github/workflows/build_and_unit_test.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_unit_test.yml b/.github/workflows/build_and_unit_test.yml index ae140f9f..c4e64a24 100644 --- a/.github/workflows/build_and_unit_test.yml +++ b/.github/workflows/build_and_unit_test.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.24" + go-version: "1.25" - name: Set Environment run: | diff --git a/go.mod b/go.mod index c39faca4..877d556e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/apache/cloudberry-backup -go 1.24.0 +go 1.25.0 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 From 69ff8f8bb733838b08babf8f768eb0d119464273 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Fri, 15 May 2026 17:46:06 +0800 Subject: [PATCH 02/10] Update go version in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d41b4b26..eb2fafaa 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ repo is a fork of gpbackup, dedicated to supporting Cloudberry. ## Pre-Requisites -The project requires the Go Programming language version 1.21 or higher. +The project requires the Go Programming language version 1.25 or higher. Follow the directions [here](https://golang.org/doc/) for installation, usage and configuration instructions. Make sure to set the [Go PATH environment variable](https://go.dev/doc/install) before starting the following steps. From 45df7a51a715558c3fbb04fdc583a63563acf091 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Tue, 19 May 2026 11:34:31 +0800 Subject: [PATCH 03/10] Upgrade go-libs to the latest --- go.mod | 8 ++-- go.sum | 143 ++++----------------------------------------------------- 2 files changed, 14 insertions(+), 137 deletions(-) diff --git a/go.mod b/go.mod index 877d556e..5151b7e1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.25.0 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/alecthomas/kingpin/v2 v2.4.0 - github.com/apache/cloudberry-go-libs v1.0.12-0.20250910014224-fc376e8a1056 + github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54 github.com/aws/aws-sdk-go v1.44.257 github.com/blang/semver v3.5.1+incompatible github.com/blang/vfs v1.0.0 @@ -51,9 +51,9 @@ require ( github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.3.3 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgtype v1.14.0 // indirect - github.com/jackc/pgx/v4 v4.18.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect + github.com/jackc/pgx/v5 v5.9.2 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 9f21e075..f8cc1fe8 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,12 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= -github.com/apache/cloudberry-go-libs v1.0.12-0.20250910014224-fc376e8a1056 h1:ycrFztmYATpidbSAU1rw60XuhuDxgBHtLD3Sueu947c= -github.com/apache/cloudberry-go-libs v1.0.12-0.20250910014224-fc376e8a1056/go.mod h1:lfHWkNYsno/lV+Nee0OoCmlOlBz5yvT6EW8WQEOUI5c= +github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54 h1:LXL2Bwi9/DBYc1Spx7HELBmuYXAF1MO84t2n4LlxXGA= +github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54/go.mod h1:HZTo9I+h7TON4BnCFlcaHCchXiEYivTuYqRCs7JnaCA= github.com/aws/aws-sdk-go v1.44.257 h1:HwelXYZZ8c34uFFhgVw3ybu2gB5fkk8KLj2idTvzZb8= github.com/aws/aws-sdk-go v1.44.257/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -23,32 +20,22 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL 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/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -57,7 +44,6 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -65,53 +51,25 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= -github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= -github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= +github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -120,34 +78,22 @@ github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -173,7 +119,6 @@ github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4 github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -190,36 +135,22 @@ github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzM github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -234,44 +165,18 @@ github.com/urfave/cli v1.22.13/go.mod h1:VufqObjsMTF2BBwKawpx9R8eAneNEWhoO0yx8Vd github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= @@ -283,17 +188,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20201119102817-f84b799fce68/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-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -304,15 +200,11 @@ golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54 h1:E2/AqCUMZGgd73TQkxUMcMla25GB9i/5HOdLr+uH7Vo= golang.org/x/telemetry v0.0.0-20251111182119-bc8e575c7b54/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.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.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= @@ -320,33 +212,19 @@ golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -354,4 +232,3 @@ 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= From 7f8314a02bf2923ca9426c4b11e8a40238a66f70 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Tue, 19 May 2026 12:12:42 +0800 Subject: [PATCH 04/10] Fix unit end_to_end test --- testutils/functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testutils/functions.go b/testutils/functions.go index 19d786aa..da86eb0d 100644 --- a/testutils/functions.go +++ b/testutils/functions.go @@ -118,7 +118,7 @@ func SetupTestDBConnSegment(dbname string, port int, host string, gpVersion dbco gpRoleGuc = "gp_role" } - connStr := fmt.Sprintf("postgres://%s@%s:%d/%s?sslmode=disable&statement_cache_capacity=0&%s=utility", conn.User, conn.Host, conn.Port, conn.DBName, gpRoleGuc) + connStr := fmt.Sprintf("postgres://%s@%s:%d/%s?sslmode=disable&default_query_exec_mode=exec&%s=utility", conn.User, conn.Host, conn.Port, conn.DBName, gpRoleGuc) segConn, err := conn.Driver.Connect("pgx", connStr) if err != nil { From c4efa2f1fe4a052d66956a4f7a6129ae507ca077 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Tue, 19 May 2026 14:01:56 +0800 Subject: [PATCH 05/10] Fix tests --- backup/backup.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backup/backup.go b/backup/backup.go index 2711f83c..9e12918d 100644 --- a/backup/backup.go +++ b/backup/backup.go @@ -624,7 +624,7 @@ type TableLocks struct { } func getTableLocks(table Table) []TableLocks { - conn := dbconn.NewDBConnFromEnvironment(MustGetFlagString(options.DBNAME)) + conn := dbconn.NewDBConnFromEnvironment(connectionPool.DBName) conn.MustConnect(1) var query string defer conn.Close() From 4b4661e1abee8759d607235ec33fc8f3960416a4 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Wed, 24 Jun 2026 18:55:18 +0800 Subject: [PATCH 06/10] Update go-libs --- end_to_end/end_to_end_suite_test.go | 2 +- end_to_end/incremental_test.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- integration/data_backup_test.go | 2 +- integration/integration_suite_test.go | 2 +- report/report.go | 2 +- report/report_test.go | 2 +- utils/plugin.go | 2 +- utils/plugin_test.go | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/end_to_end/end_to_end_suite_test.go b/end_to_end/end_to_end_suite_test.go index a21a5977..76a5b370 100644 --- a/end_to_end/end_to_end_suite_test.go +++ b/end_to_end/end_to_end_suite_test.go @@ -29,7 +29,7 @@ import ( "github.com/apache/cloudberry-go-libs/operating" "github.com/apache/cloudberry-go-libs/structmatcher" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" _ "github.com/mattn/go-sqlite3" "github.com/pkg/errors" "github.com/spf13/pflag" diff --git a/end_to_end/incremental_test.go b/end_to_end/incremental_test.go index 50a15802..6434250f 100644 --- a/end_to_end/incremental_test.go +++ b/end_to_end/incremental_test.go @@ -9,7 +9,7 @@ import ( "github.com/apache/cloudberry-backup/history" "github.com/apache/cloudberry-go-libs/dbconn" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/go.mod b/go.mod index 5151b7e1..82aa29b8 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.25.0 require ( github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/alecthomas/kingpin/v2 v2.4.0 - github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54 + github.com/apache/cloudberry-go-libs v1.0.12-0.20260624080114-3de23e29a87a github.com/aws/aws-sdk-go v1.44.257 - github.com/blang/semver v3.5.1+incompatible + github.com/blang/semver/v4 v4.0.0 github.com/blang/vfs v1.0.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf github.com/jackc/pgconn v1.14.3 diff --git a/go.sum b/go.sum index f8cc1fe8..52082276 100644 --- a/go.sum +++ b/go.sum @@ -5,14 +5,14 @@ github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjH github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0= github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs= -github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54 h1:LXL2Bwi9/DBYc1Spx7HELBmuYXAF1MO84t2n4LlxXGA= -github.com/apache/cloudberry-go-libs v1.0.12-0.20260516112723-b2dee8a6ae54/go.mod h1:HZTo9I+h7TON4BnCFlcaHCchXiEYivTuYqRCs7JnaCA= +github.com/apache/cloudberry-go-libs v1.0.12-0.20260624080114-3de23e29a87a h1:xDVS0fObqCupd0eBTdk1OQC5vQJ9YD7KCyAsnP8zZXw= +github.com/apache/cloudberry-go-libs v1.0.12-0.20260624080114-3de23e29a87a/go.mod h1:yaH60R8eMGETbTAAxrcBVXJ0T7WwWXPddm2LWLKB7kI= github.com/aws/aws-sdk-go v1.44.257 h1:HwelXYZZ8c34uFFhgVw3ybu2gB5fkk8KLj2idTvzZb8= github.com/aws/aws-sdk-go v1.44.257/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blang/vfs v1.0.0 h1:AUZUgulCDzbaNjTRWEP45X7m/J10brAptZpSRKRZBZc= github.com/blang/vfs v1.0.0/go.mod h1:jjuNUc/IKcRNNWC9NUCvz4fR9PZLPIKxEygtPs/4tSI= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= diff --git a/integration/data_backup_test.go b/integration/data_backup_test.go index 7e8ba574..1df7a916 100644 --- a/integration/data_backup_test.go +++ b/integration/data_backup_test.go @@ -11,7 +11,7 @@ import ( "github.com/apache/cloudberry-backup/utils" "github.com/apache/cloudberry-go-libs/gplog" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/integration/integration_suite_test.go b/integration/integration_suite_test.go index da5627b5..ba87342d 100644 --- a/integration/integration_suite_test.go +++ b/integration/integration_suite_test.go @@ -16,7 +16,7 @@ import ( "github.com/apache/cloudberry-go-libs/dbconn" "github.com/apache/cloudberry-go-libs/gplog" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/spf13/pflag" . "github.com/onsi/ginkgo/v2" diff --git a/report/report.go b/report/report.go index d50ad9e5..8278775e 100644 --- a/report/report.go +++ b/report/report.go @@ -16,7 +16,7 @@ import ( "github.com/apache/cloudberry-go-libs/gplog" "github.com/apache/cloudberry-go-libs/iohelper" "github.com/apache/cloudberry-go-libs/operating" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/pkg/errors" "gopkg.in/yaml.v2" ) diff --git a/report/report_test.go b/report/report_test.go index e53cc2de..f01066eb 100644 --- a/report/report_test.go +++ b/report/report_test.go @@ -20,7 +20,7 @@ import ( "github.com/apache/cloudberry-go-libs/operating" "github.com/apache/cloudberry-go-libs/structmatcher" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/pkg/errors" "github.com/spf13/pflag" "gopkg.in/yaml.v2" diff --git a/utils/plugin.go b/utils/plugin.go index e1e9b1a2..93d09924 100644 --- a/utils/plugin.go +++ b/utils/plugin.go @@ -14,7 +14,7 @@ import ( "github.com/apache/cloudberry-go-libs/gplog" "github.com/apache/cloudberry-go-libs/iohelper" "github.com/apache/cloudberry-go-libs/operating" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/pkg/errors" "gopkg.in/yaml.v2" ) diff --git a/utils/plugin_test.go b/utils/plugin_test.go index 2fc22cf9..99989b1d 100644 --- a/utils/plugin_test.go +++ b/utils/plugin_test.go @@ -13,7 +13,7 @@ import ( "github.com/apache/cloudberry-go-libs/iohelper" "github.com/apache/cloudberry-go-libs/operating" "github.com/apache/cloudberry-go-libs/testhelper" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/pkg/errors" . "github.com/onsi/ginkgo/v2" From 5253c120db68299176cb361bf0c35d07d062f27b Mon Sep 17 00:00:00 2001 From: woblerr Date: Fri, 26 Jun 2026 00:02:22 +0300 Subject: [PATCH 07/10] Fix deadlock e2e test transaction handling. The test held locks with raw BEGIN/COMMIT SQL on DBConn and then reused the same connection for polling. With pgx v5 this can release the raw transaction lock, so gpbackup was not blocked and the test observed 0 deadlock traps. Use explicit DBConn transactions, separate polling connections, wait for goroutines before closing connections, and wait for the expected 2 blocked AccessExclusiveLock requests. --- end_to_end/locks_test.go | 61 +++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/end_to_end/locks_test.go b/end_to_end/locks_test.go index 8b7ee35d..b05b1d17 100644 --- a/end_to_end/locks_test.go +++ b/end_to_end/locks_test.go @@ -3,6 +3,7 @@ package end_to_end_test import ( "fmt" "os/exec" + "sync" "time" "github.com/apache/cloudberry-backup/backup" @@ -290,7 +291,11 @@ var _ = Describe("Deadlock handling", func() { } // Acquire AccessExclusiveLock on public.foo to block gpbackup when it attempts // to grab AccessShareLocks before its metadata dump section. - backupConn.MustExec("BEGIN; LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") + initialLockConn := testutils.SetupTestDbConn("testdb") + defer initialLockConn.Close() + initialLockConn.MustBegin() + defer func() { _ = initialLockConn.Rollback() }() + initialLockConn.MustExec("LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", @@ -298,13 +303,25 @@ var _ = Describe("Deadlock handling", func() { "--jobs", "2", "--verbose"} cmd := exec.Command(gpbackupPath, args...) + + var wg sync.WaitGroup + releaseTriggerLock := make(chan struct{}) + var releaseTriggerLockOnce sync.Once + defer func() { + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) + wg.Wait() + }() + // Concurrently wait for gpbackup to block when it requests an AccessShareLock on public.foo. Once // that happens, acquire an AccessExclusiveLock on pg_catalog.pg_trigger to block gpbackup during its // trigger metadata dump. Then release the initial AccessExclusiveLock on public.foo (from the // beginning of the test) to unblock gpbackup and let gpbackup move forward to the trigger metadata dump. - anotherConn := testutils.SetupTestDbConn("testdb") - defer anotherConn.Close() + wg.Add(1) go func() { + defer wg.Done() + triggerLockConn := testutils.SetupTestDbConn("testdb") + defer triggerLockConn.Close() + // Query to see if gpbackup's AccessShareLock request on public.foo is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'public' AND c.relname = 'foo' AND l.granted = 'f' AND l.mode = 'AccessShareLock'` @@ -312,7 +329,7 @@ var _ = Describe("Deadlock handling", func() { var gpbackupBlockedLockCount int iterations := 100 for iterations > 0 { - _ = anotherConn.Get(&gpbackupBlockedLockCount, checkLockQuery) + _ = triggerLockConn.Get(&gpbackupBlockedLockCount, checkLockQuery) if gpbackupBlockedLockCount < 1 { time.Sleep(100 * time.Millisecond) iterations-- @@ -325,8 +342,12 @@ var _ = Describe("Deadlock handling", func() { // during the trigger metadata dump so that the test can queue a bunch of // AccessExclusiveLock requests against the test tables. Afterwards, release the // AccessExclusiveLock on public.foo to let gpbackup go to the trigger metadata dump. - anotherConn.MustExec(`BEGIN; LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) - backupConn.MustExec("COMMIT") + triggerLockConn.MustBegin() + defer func() { _ = triggerLockConn.Rollback() }() + triggerLockConn.MustExec(`LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) + initialLockConn.MustCommit() + <-releaseTriggerLock + triggerLockConn.MustCommit() }() // Concurrently wait for gpbackup to block on the trigger metadata dump section. Once we @@ -336,7 +357,9 @@ var _ = Describe("Deadlock handling", func() { "schema2.ao1", "schema2.ao2", "schema2.foo2", "schema2.foo3", "schema2.returns"} lockedTables := []string{`public."FOObar"`, "public.foo"} for _, lockedTable := range lockedTables { + wg.Add(1) go func(lockedTable string) { + defer wg.Done() accessExclusiveLockConn := testutils.SetupTestDbConn("testdb") defer accessExclusiveLockConn.Close() @@ -357,23 +380,32 @@ var _ = Describe("Deadlock handling", func() { } // Queue an AccessExclusiveLock request on a test table which will later // result in a detected deadlock during the gpbackup data dump section. - accessExclusiveLockConn.MustExec(fmt.Sprintf(`BEGIN; LOCK TABLE %s IN ACCESS EXCLUSIVE MODE; COMMIT`, lockedTable)) + accessExclusiveLockConn.MustBegin() + defer func() { _ = accessExclusiveLockConn.Rollback() }() + accessExclusiveLockConn.MustExec(fmt.Sprintf(`LOCK TABLE %s IN ACCESS EXCLUSIVE MODE`, lockedTable)) + accessExclusiveLockConn.MustCommit() }(lockedTable) } - // Concurrently wait for all AccessExclusiveLock requests on all 10 test tables to block. + // Concurrently wait for all AccessExclusiveLock requests on all locked test tables to block. // Once that happens, release the AccessExclusiveLock on pg_catalog.pg_trigger to unblock // gpbackup and let gpbackup move forward to the data dump section. - var accessExclBlockedLockCount int + accessExclBlockedLockCountChan := make(chan int, 1) + wg.Add(1) go func() { + defer wg.Done() + accessExclBlockedLockConn := testutils.SetupTestDbConn("testdb") + defer accessExclBlockedLockConn.Close() + // Query to check for ungranted AccessExclusiveLock requests on our test tables checkLockQuery := `SELECT count(*) FROM pg_locks WHERE granted = 'f' AND mode = 'AccessExclusiveLock'` // Wait up to 10 seconds + var accessExclBlockedLockCount int iterations := 100 for iterations > 0 { - _ = backupConn.Get(&accessExclBlockedLockCount, checkLockQuery) - if accessExclBlockedLockCount < 9 { + _ = accessExclBlockedLockConn.Get(&accessExclBlockedLockCount, checkLockQuery) + if accessExclBlockedLockCount < len(lockedTables) { time.Sleep(100 * time.Millisecond) iterations-- } else { @@ -382,12 +414,15 @@ var _ = Describe("Deadlock handling", func() { } // Unblock gpbackup by releasing AccessExclusiveLock on pg_catalog.pg_trigger - anotherConn.MustExec("COMMIT") + accessExclBlockedLockCountChan <- accessExclBlockedLockCount + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) }() // gpbackup has finished - output, _ := cmd.CombinedOutput() + output, err := cmd.CombinedOutput() stdout := string(output) + accessExclBlockedLockCount := <-accessExclBlockedLockCountChan + Expect(err).ToNot(HaveOccurred(), "%s", stdout) // Check that 2 deadlock traps were placed during the test Expect(accessExclBlockedLockCount).To(Equal(2)) From 365aedf5a36a7482401c7b4441c226d3bd047acd Mon Sep 17 00:00:00 2001 From: woblerr Date: Fri, 26 Jun 2026 00:08:18 +0300 Subject: [PATCH 08/10] Fix pgx v5 PgError handling. After moving to pgx v5, database errors are returned as pgx/v5/pgconn.PgError. The old jackc/pgconn type assertions no longer matched, so backup lock handling could treat unexpected errors as lock-not-available, and restore COPY errors could lose their CONTEXT. Use errors.As with pgx/v5 pgconn in backup and restore code, update the restore test, and remove the old pgconn dependency. --- backup/data.go | 12 +++++++++--- go.mod | 6 +----- go.sum | 11 ----------- restore/data.go | 5 +++-- restore/data_test.go | 2 +- 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/backup/data.go b/backup/data.go index 9d937bae..e4571408 100644 --- a/backup/data.go +++ b/backup/data.go @@ -16,7 +16,7 @@ import ( "github.com/apache/cloudberry-backup/utils" "github.com/apache/cloudberry-go-libs/dbconn" "github.com/apache/cloudberry-go-libs/gplog" - "github.com/jackc/pgconn" + "github.com/jackc/pgx/v5/pgconn" "gopkg.in/cheggaaa/pb.v1" ) @@ -214,13 +214,19 @@ func BackupDataForAllTables(tables []Table) []map[uint32]int64 { // tables before the metadata dumping part. err := LockTableNoWait(table, whichConn) if err != nil { - if pgErr, ok := err.(*pgconn.PgError); ok && pgErr.Code != PG_LOCK_NOT_AVAILABLE { + lockErr := err + var pgErr *pgconn.PgError + if !errors.As(lockErr, &pgErr) || pgErr.Code != PG_LOCK_NOT_AVAILABLE { isErroredBackup.Store(true) err = connectionPool.Rollback(whichConn) if err != nil { gplog.Warn("Worker %d: %s", whichConn, err) } - gplog.Fatal(fmt.Errorf("Unexpectedly unable to take lock on table %s, %s", table.FQN(), pgErr.Error()), "") + errMsg := lockErr.Error() + if pgErr != nil { + errMsg = pgErr.Error() + } + gplog.Fatal(fmt.Errorf("Unexpectedly unable to take lock on table %s, %s", table.FQN(), errMsg), "") } if gplog.GetVerbosity() < gplog.LOGVERBOSE { // Add a newline to interrupt the progress bar so that diff --git a/go.mod b/go.mod index 82aa29b8..37ab24fc 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/blang/semver/v4 v4.0.0 github.com/blang/vfs v1.0.0 github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf - github.com/jackc/pgconn v1.14.3 + github.com/jackc/pgx/v5 v5.9.2 github.com/jmoiron/sqlx v1.3.5 github.com/klauspost/compress v1.18.0 github.com/lib/pq v1.10.7 @@ -47,12 +47,8 @@ require ( github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/google/uuid v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.9.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect diff --git a/go.sum b/go.sum index 52082276..1de9bbcf 100644 --- a/go.sum +++ b/go.sum @@ -51,19 +51,8 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf h1:FtEj8sfIcaaBfAKrE1Cwb61YDtYq9JxChK1c7AKce7s= github.com/inhies/go-bytesize v0.0.0-20220417184213-4913239db9cf/go.mod h1:yrqSXGoD/4EKfF26AOGzscPOgTTJcyAwM2rpixWT+t4= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= -github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= -github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= diff --git a/restore/data.go b/restore/data.go index 44d21120..13ec4218 100644 --- a/restore/data.go +++ b/restore/data.go @@ -16,7 +16,7 @@ import ( "github.com/apache/cloudberry-go-libs/cluster" "github.com/apache/cloudberry-go-libs/dbconn" "github.com/apache/cloudberry-go-libs/gplog" - "github.com/jackc/pgconn" + "github.com/jackc/pgx/v5/pgconn" "github.com/pkg/errors" "gopkg.in/cheggaaa/pb.v1" ) @@ -60,7 +60,8 @@ func CopyTableIn(connectionPool *dbconn.DBConn, tableName string, tableAttribute errStr := fmt.Sprintf("Error loading data into table %s", tableName) // The COPY ON SEGMENT error might contain useful CONTEXT output - if pgErr, ok := err.(*pgconn.PgError); ok && pgErr.Where != "" { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) && pgErr.Where != "" { errStr = fmt.Sprintf("%s: %s", errStr, pgErr.Where) } diff --git a/restore/data_test.go b/restore/data_test.go index 01a03b05..2e1c9da4 100644 --- a/restore/data_test.go +++ b/restore/data_test.go @@ -10,7 +10,7 @@ import ( "github.com/apache/cloudberry-backup/restore" "github.com/apache/cloudberry-backup/utils" "github.com/apache/cloudberry-go-libs/cluster" - "github.com/jackc/pgconn" + "github.com/jackc/pgx/v5/pgconn" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" From 2861f472b71a9949bed5e91d8b9f98fa48ad24d4 Mon Sep 17 00:00:00 2001 From: woblerr Date: Fri, 26 Jun 2026 13:09:08 +0300 Subject: [PATCH 09/10] Fix lock e2e test transaction handling. The deadlock and signal handler e2e tests still held locks with raw BEGIN/COMMIT SQL on DBConn and reused those connections for pg_locks polling. With pgx v5 this can release the raw transaction lock or leave goroutines polling on closed connections, causing missing blocked-lock counts and DBConn.Get panics. Use explicit transactions, dedicated lock and polling connections, and synchronize goroutines before closing test connections. --- end_to_end/locks_test.go | 119 +++++++++++++++++++++------ end_to_end/signal_handler_test.go | 129 ++++++++++++------------------ 2 files changed, 142 insertions(+), 106 deletions(-) diff --git a/end_to_end/locks_test.go b/end_to_end/locks_test.go index b05b1d17..046a5730 100644 --- a/end_to_end/locks_test.go +++ b/end_to_end/locks_test.go @@ -28,7 +28,11 @@ var _ = Describe("Deadlock handling", func() { } // Acquire AccessExclusiveLock on public.foo to block gpbackup when it attempts // to grab AccessShareLocks before its metadata dump section. - backupConn.MustExec("BEGIN; LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") + initialLockConn := testutils.SetupTestDbConn("testdb") + defer initialLockConn.Close() + initialLockConn.MustBegin() + defer func() { _ = initialLockConn.Rollback() }() + initialLockConn.MustExec("LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") // Execute gpbackup with --jobs 10 since there are 10 tables to back up args := []string{ @@ -37,13 +41,25 @@ var _ = Describe("Deadlock handling", func() { "--jobs", "10", "--verbose"} cmd := exec.Command(gpbackupPath, args...) + + var wg sync.WaitGroup + releaseTriggerLock := make(chan struct{}) + var releaseTriggerLockOnce sync.Once + defer func() { + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) + wg.Wait() + }() + // Concurrently wait for gpbackup to block when it requests an AccessShareLock on public.foo. Once // that happens, acquire an AccessExclusiveLock on pg_catalog.pg_trigger to block gpbackup during its // trigger metadata dump. Then release the initial AccessExclusiveLock on public.foo (from the // beginning of the test) to unblock gpbackup and let gpbackup move forward to the trigger metadata dump. - anotherConn := testutils.SetupTestDbConn("testdb") - defer anotherConn.Close() + wg.Add(1) go func() { + defer wg.Done() + triggerLockConn := testutils.SetupTestDbConn("testdb") + defer triggerLockConn.Close() + // Query to see if gpbackup's AccessShareLock request on public.foo is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'public' AND c.relname = 'foo' AND l.granted = 'f' AND l.mode = 'AccessShareLock'` @@ -51,7 +67,7 @@ var _ = Describe("Deadlock handling", func() { var gpbackupBlockedLockCount int iterations := 100 for iterations > 0 { - _ = anotherConn.Get(&gpbackupBlockedLockCount, checkLockQuery) + _ = triggerLockConn.Get(&gpbackupBlockedLockCount, checkLockQuery) if gpbackupBlockedLockCount < 1 { time.Sleep(100 * time.Millisecond) iterations-- @@ -64,8 +80,12 @@ var _ = Describe("Deadlock handling", func() { // during the trigger metadata dump so that the test can queue a bunch of // AccessExclusiveLock requests against the test tables. Afterwards, release the // AccessExclusiveLock on public.foo to let gpbackup go to the trigger metadata dump. - anotherConn.MustExec(`BEGIN; LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) - backupConn.MustExec("COMMIT") + triggerLockConn.MustBegin() + defer func() { _ = triggerLockConn.Rollback() }() + triggerLockConn.MustExec(`LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) + initialLockConn.MustCommit() + <-releaseTriggerLock + triggerLockConn.MustCommit() }() // Concurrently wait for gpbackup to block on the trigger metadata dump section. Once we @@ -74,7 +94,9 @@ var _ = Describe("Deadlock handling", func() { dataTables := []string{`public."FOObar"`, "public.foo", "public.holds", "public.sales", "public.bigtable", "schema2.ao1", "schema2.ao2", "schema2.foo2", "schema2.foo3", "schema2.returns"} for _, dataTable := range dataTables { + wg.Add(1) go func(dataTable string) { + defer wg.Done() accessExclusiveLockConn := testutils.SetupTestDbConn("testdb") defer accessExclusiveLockConn.Close() @@ -96,23 +118,32 @@ var _ = Describe("Deadlock handling", func() { // Queue an AccessExclusiveLock request on a test table which will later // result in a detected deadlock during the gpbackup data dump section. - accessExclusiveLockConn.MustExec(fmt.Sprintf(`BEGIN; LOCK TABLE %s IN ACCESS EXCLUSIVE MODE; COMMIT`, dataTable)) + accessExclusiveLockConn.MustBegin() + defer func() { _ = accessExclusiveLockConn.Rollback() }() + accessExclusiveLockConn.MustExec(fmt.Sprintf(`LOCK TABLE %s IN ACCESS EXCLUSIVE MODE`, dataTable)) + accessExclusiveLockConn.MustCommit() }(dataTable) } // Concurrently wait for all AccessExclusiveLock requests on all 10 test tables to block. // Once that happens, release the AccessExclusiveLock on pg_catalog.pg_trigger to unblock // gpbackup and let gpbackup move forward to the data dump section. - var accessExclBlockedLockCount int + accessExclBlockedLockCountChan := make(chan int, 1) + wg.Add(1) go func() { + defer wg.Done() + accessExclBlockedLockConn := testutils.SetupTestDbConn("testdb") + defer accessExclBlockedLockConn.Close() + // Query to check for ungranted AccessExclusiveLock requests on our test tables checkLockQuery := `SELECT count(*) FROM pg_locks WHERE granted = 'f' AND mode = 'AccessExclusiveLock'` // Wait up to 10 seconds + var accessExclBlockedLockCount int iterations := 100 for iterations > 0 { - _ = backupConn.Get(&accessExclBlockedLockCount, checkLockQuery) - if accessExclBlockedLockCount < 10 { + _ = accessExclBlockedLockConn.Get(&accessExclBlockedLockCount, checkLockQuery) + if accessExclBlockedLockCount < len(dataTables) { time.Sleep(100 * time.Millisecond) iterations-- } else { @@ -121,15 +152,18 @@ var _ = Describe("Deadlock handling", func() { } // Unblock gpbackup by releasing AccessExclusiveLock on pg_catalog.pg_trigger - anotherConn.MustExec("COMMIT") + accessExclBlockedLockCountChan <- accessExclBlockedLockCount + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) }() // gpbackup has finished - output, _ := cmd.CombinedOutput() + output, err := cmd.CombinedOutput() stdout := string(output) + accessExclBlockedLockCount := <-accessExclBlockedLockCountChan + Expect(err).ToNot(HaveOccurred(), "%s", stdout) // Check that 10 deadlock traps were placed during the test - Expect(accessExclBlockedLockCount).To(Equal(10)) + Expect(accessExclBlockedLockCount).To(Equal(len(dataTables))) // No non-main worker should have been able to run COPY due to deadlock detection for i := 1; i < 10; i++ { expectedLockString := fmt.Sprintf("[DEBUG]:-Worker %d: LOCK TABLE ", i) @@ -156,7 +190,11 @@ var _ = Describe("Deadlock handling", func() { } // Acquire AccessExclusiveLock on public.foo to block gpbackup when it attempts // to grab AccessShareLocks before its metadata dump section. - backupConn.MustExec("BEGIN; LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") + initialLockConn := testutils.SetupTestDbConn("testdb") + defer initialLockConn.Close() + initialLockConn.MustBegin() + defer func() { _ = initialLockConn.Rollback() }() + initialLockConn.MustExec("LOCK TABLE public.foo IN ACCESS EXCLUSIVE MODE") // Execute gpbackup with --copy-queue-size 2 args := []string{ @@ -167,13 +205,24 @@ var _ = Describe("Deadlock handling", func() { "--verbose"} cmd := exec.Command(gpbackupPath, args...) + var wg sync.WaitGroup + releaseTriggerLock := make(chan struct{}) + var releaseTriggerLockOnce sync.Once + defer func() { + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) + wg.Wait() + }() + // Concurrently wait for gpbackup to block when it requests an AccessShareLock on public.foo. Once // that happens, acquire an AccessExclusiveLock on pg_catalog.pg_trigger to block gpbackup during its // trigger metadata dump. Then release the initial AccessExclusiveLock on public.foo (from the // beginning of the test) to unblock gpbackup and let gpbackup move forward to the trigger metadata dump. - anotherConn := testutils.SetupTestDbConn("testdb") - defer anotherConn.Close() + wg.Add(1) go func() { + defer wg.Done() + triggerLockConn := testutils.SetupTestDbConn("testdb") + defer triggerLockConn.Close() + // Query to see if gpbackup's AccessShareLock request on public.foo is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'public' AND c.relname = 'foo' AND l.granted = 'f' AND l.mode = 'AccessShareLock'` @@ -181,7 +230,7 @@ var _ = Describe("Deadlock handling", func() { var gpbackupBlockedLockCount int iterations := 100 for iterations > 0 { - _ = anotherConn.Get(&gpbackupBlockedLockCount, checkLockQuery) + _ = triggerLockConn.Get(&gpbackupBlockedLockCount, checkLockQuery) if gpbackupBlockedLockCount < 1 { time.Sleep(100 * time.Millisecond) iterations-- @@ -194,8 +243,12 @@ var _ = Describe("Deadlock handling", func() { // during the trigger metadata dump so that the test can queue a bunch of // AccessExclusiveLock requests against the test tables. Afterwards, release the // AccessExclusiveLock on public.foo to let gpbackup go to the trigger metadata dump. - anotherConn.MustExec(`BEGIN; LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) - backupConn.MustExec("COMMIT") + triggerLockConn.MustBegin() + defer func() { _ = triggerLockConn.Rollback() }() + triggerLockConn.MustExec(`LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE`) + initialLockConn.MustCommit() + <-releaseTriggerLock + triggerLockConn.MustCommit() }() // Concurrently wait for gpbackup to block on the trigger metadata dump section. Once we @@ -204,7 +257,9 @@ var _ = Describe("Deadlock handling", func() { dataTables := []string{`public."FOObar"`, "public.foo", "public.holds", "public.sales", "public.bigtable", "schema2.ao1", "schema2.ao2", "schema2.foo2", "schema2.foo3", "schema2.returns"} for _, dataTable := range dataTables { + wg.Add(1) go func(dataTable string) { + defer wg.Done() accessExclusiveLockConn := testutils.SetupTestDbConn("testdb") defer accessExclusiveLockConn.Close() @@ -226,23 +281,32 @@ var _ = Describe("Deadlock handling", func() { // Queue an AccessExclusiveLock request on a test table which will later // result in a detected deadlock during the gpbackup data dump section. - accessExclusiveLockConn.MustExec(fmt.Sprintf(`BEGIN; LOCK TABLE %s IN ACCESS EXCLUSIVE MODE; COMMIT`, dataTable)) + accessExclusiveLockConn.MustBegin() + defer func() { _ = accessExclusiveLockConn.Rollback() }() + accessExclusiveLockConn.MustExec(fmt.Sprintf(`LOCK TABLE %s IN ACCESS EXCLUSIVE MODE`, dataTable)) + accessExclusiveLockConn.MustCommit() }(dataTable) } // Concurrently wait for all AccessExclusiveLock requests on all 10 test tables to block. // Once that happens, release the AccessExclusiveLock on pg_catalog.pg_trigger to unblock // gpbackup and let gpbackup move forward to the data dump section. - var accessExclBlockedLockCount int + accessExclBlockedLockCountChan := make(chan int, 1) + wg.Add(1) go func() { + defer wg.Done() + accessExclBlockedLockConn := testutils.SetupTestDbConn("testdb") + defer accessExclBlockedLockConn.Close() + // Query to check for ungranted AccessExclusiveLock requests on our test tables checkLockQuery := `SELECT count(*) FROM pg_locks WHERE granted = 'f' AND mode = 'AccessExclusiveLock'` // Wait up to 10 seconds + var accessExclBlockedLockCount int iterations := 100 for iterations > 0 { - _ = backupConn.Get(&accessExclBlockedLockCount, checkLockQuery) - if accessExclBlockedLockCount < 10 { + _ = accessExclBlockedLockConn.Get(&accessExclBlockedLockCount, checkLockQuery) + if accessExclBlockedLockCount < len(dataTables) { time.Sleep(100 * time.Millisecond) iterations-- } else { @@ -251,15 +315,18 @@ var _ = Describe("Deadlock handling", func() { } // Unblock gpbackup by releasing AccessExclusiveLock on pg_catalog.pg_trigger - anotherConn.MustExec("COMMIT") + accessExclBlockedLockCountChan <- accessExclBlockedLockCount + releaseTriggerLockOnce.Do(func() { close(releaseTriggerLock) }) }() // gpbackup has finished - output, _ := cmd.CombinedOutput() + output, err := cmd.CombinedOutput() stdout := string(output) + accessExclBlockedLockCount := <-accessExclBlockedLockCountChan + Expect(err).ToNot(HaveOccurred(), "%s", stdout) // Check that 10 deadlock traps were placed during the test - Expect(accessExclBlockedLockCount).To(Equal(10)) + Expect(accessExclBlockedLockCount).To(Equal(len(dataTables))) // No non-main worker should have been able to run COPY due to deadlock detection for i := 1; i < 2; i++ { expectedLockString := fmt.Sprintf("[DEBUG]:-Worker %d: LOCK TABLE ", i) diff --git a/end_to_end/signal_handler_test.go b/end_to_end/signal_handler_test.go index e10c399e..95c7a07e 100644 --- a/end_to_end/signal_handler_test.go +++ b/end_to_end/signal_handler_test.go @@ -2,15 +2,60 @@ package end_to_end_test import ( "math/rand" + "os" "os/exec" "time" + "github.com/apache/cloudberry-backup/testutils" "github.com/apache/cloudberry-go-libs/testhelper" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "golang.org/x/sys/unix" ) +func gpbackupWithBlockedFoo2LockSignal(cmd *exec.Cmd, sig os.Signal, checkLockQuery string) ([]byte, int, int) { + lockConn := testutils.SetupTestDbConn("testdb") + defer lockConn.Close() + lockConn.MustBegin() + defer func() { _ = lockConn.Rollback() }() + lockConn.MustExec("LOCK TABLE schema2.foo2 IN ACCESS EXCLUSIVE MODE") + + beforeLockCountChan := make(chan int, 1) + signalDone := make(chan struct{}) + go func() { + defer close(signalDone) + lockCheckConn := testutils.SetupTestDbConn("testdb") + defer lockCheckConn.Close() + + var beforeLockCount int + iterations := 50 + for iterations > 0 { + _ = lockCheckConn.Get(&beforeLockCount, checkLockQuery) + if beforeLockCount < 1 { + time.Sleep(100 * time.Millisecond) + iterations-- + } else { + break + } + } + beforeLockCountChan <- beforeLockCount + if cmd.Process != nil { + _ = cmd.Process.Signal(sig) + } + }() + + output, _ := cmd.CombinedOutput() + <-signalDone + beforeLockCount := <-beforeLockCountChan + + afterLockCountConn := testutils.SetupTestDbConn("testdb") + defer afterLockCountConn.Close() + var afterLockCount int + _ = afterLockCountConn.Get(&afterLockCount, checkLockQuery) + + return output, beforeLockCount, afterLockCount +} + var _ = Describe("Signal handler tests", func() { BeforeEach(func() { end_to_end_setup() @@ -90,8 +135,6 @@ var _ = Describe("Signal handler tests", func() { // Query to see if gpbackup lock acquire on schema2.foo2 is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'schema2' AND c.relname = 'foo2' AND l.granted = 'f'` - // Acquire AccessExclusiveLock on schema2.foo2 to prevent gpbackup from acquiring AccessShareLock - backupConn.MustExec("BEGIN; LOCK TABLE schema2.foo2 IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", "--backup-dir", backupDir, @@ -100,29 +143,12 @@ var _ = Describe("Signal handler tests", func() { // Wait up to 5 seconds for gpbackup to block on acquiring AccessShareLock. // Once blocked, we send a SIGINT to cancel gpbackup. - var beforeLockCount int - go func() { - iterations := 50 - for iterations > 0 { - _ = backupConn.Get(&beforeLockCount, checkLockQuery) - if beforeLockCount < 1 { - time.Sleep(100 * time.Millisecond) - iterations-- - } else { - break - } - } - _ = cmd.Process.Signal(unix.SIGINT) - }() - output, _ := cmd.CombinedOutput() + output, beforeLockCount, afterLockCount := gpbackupWithBlockedFoo2LockSignal(cmd, unix.SIGINT, checkLockQuery) Expect(beforeLockCount).To(Equal(1)) // After gpbackup has been canceled, we should no longer see a blocked SQL // session trying to acquire AccessShareLock on foo2. - var afterLockCount int - _ = backupConn.Get(&afterLockCount, checkLockQuery) Expect(afterLockCount).To(Equal(0)) - backupConn.MustExec("ROLLBACK") stdout := string(output) Expect(stdout).To(ContainSubstring("Received an interrupt signal, aborting backup process")) @@ -140,8 +166,6 @@ var _ = Describe("Signal handler tests", func() { // Query to see if gpbackup lock acquire on schema2.foo2 is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'schema2' AND c.relname = 'foo2' AND l.granted = 'f'` - // Acquire AccessExclusiveLock on schema2.foo2 to prevent gpbackup from acquiring AccessShareLock - backupConn.MustExec("BEGIN; LOCK TABLE schema2.foo2 IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", "--backup-dir", backupDir, @@ -151,29 +175,12 @@ var _ = Describe("Signal handler tests", func() { // Wait up to 5 seconds for gpbackup to block on acquiring AccessShareLock. // Once blocked, we send a SIGINT to cancel gpbackup. - var beforeLockCount int - go func() { - iterations := 50 - for iterations > 0 { - _ = backupConn.Get(&beforeLockCount, checkLockQuery) - if beforeLockCount < 1 { - time.Sleep(100 * time.Millisecond) - iterations-- - } else { - break - } - } - _ = cmd.Process.Signal(unix.SIGINT) - }() - output, _ := cmd.CombinedOutput() + output, beforeLockCount, afterLockCount := gpbackupWithBlockedFoo2LockSignal(cmd, unix.SIGINT, checkLockQuery) Expect(beforeLockCount).To(Equal(1)) // After gpbackup has been canceled, we should no longer see a blocked SQL // session trying to acquire AccessShareLock on foo2. - var afterLockCount int - _ = backupConn.Get(&afterLockCount, checkLockQuery) Expect(afterLockCount).To(Equal(0)) - backupConn.MustExec("ROLLBACK") stdout := string(output) Expect(stdout).To(ContainSubstring("Received an interrupt signal, aborting backup process")) @@ -319,8 +326,6 @@ var _ = Describe("Signal handler tests", func() { // Query to see if gpbackup lock acquire on schema2.foo2 is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'schema2' AND c.relname = 'foo2' AND l.granted = 'f'` - // Acquire AccessExclusiveLock on schema2.foo2 to prevent gpbackup from acquiring AccessShareLock - backupConn.MustExec("BEGIN; LOCK TABLE schema2.foo2 IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", "--backup-dir", backupDir, @@ -329,29 +334,12 @@ var _ = Describe("Signal handler tests", func() { // Wait up to 5 seconds for gpbackup to block on acquiring AccessShareLock. // Once blocked, we send a SIGTERM to cancel gpbackup. - var beforeLockCount int - go func() { - iterations := 50 - for iterations > 0 { - _ = backupConn.Get(&beforeLockCount, checkLockQuery) - if beforeLockCount < 1 { - time.Sleep(100 * time.Millisecond) - iterations-- - } else { - break - } - } - _ = cmd.Process.Signal(unix.SIGTERM) - }() - output, _ := cmd.CombinedOutput() + output, beforeLockCount, afterLockCount := gpbackupWithBlockedFoo2LockSignal(cmd, unix.SIGTERM, checkLockQuery) Expect(beforeLockCount).To(Equal(1)) // After gpbackup has been canceled, we should no longer see a blocked SQL // session trying to acquire AccessShareLock on foo2. - var afterLockCount int - _ = backupConn.Get(&afterLockCount, checkLockQuery) Expect(afterLockCount).To(Equal(0)) - backupConn.MustExec("ROLLBACK") stdout := string(output) Expect(stdout).To(ContainSubstring("Received a termination signal, aborting backup process")) @@ -369,8 +357,6 @@ var _ = Describe("Signal handler tests", func() { // Query to see if gpbackup lock acquire on schema2.foo2 is blocked checkLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'schema2' AND c.relname = 'foo2' AND l.granted = 'f'` - // Acquire AccessExclusiveLock on schema2.foo2 to prevent gpbackup from acquiring AccessShareLock - backupConn.MustExec("BEGIN; LOCK TABLE schema2.foo2 IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", "--backup-dir", backupDir, @@ -380,29 +366,12 @@ var _ = Describe("Signal handler tests", func() { // Wait up to 5 seconds for gpbackup to block on acquiring AccessShareLock. // Once blocked, we send a SIGTERM to cancel gpbackup. - var beforeLockCount int - go func() { - iterations := 50 - for iterations > 0 { - _ = backupConn.Get(&beforeLockCount, checkLockQuery) - if beforeLockCount < 1 { - time.Sleep(100 * time.Millisecond) - iterations-- - } else { - break - } - } - _ = cmd.Process.Signal(unix.SIGTERM) - }() - output, _ := cmd.CombinedOutput() + output, beforeLockCount, afterLockCount := gpbackupWithBlockedFoo2LockSignal(cmd, unix.SIGTERM, checkLockQuery) Expect(beforeLockCount).To(Equal(1)) // After gpbackup has been canceled, we should no longer see a blocked SQL // session trying to acquire AccessShareLock on foo2. - var afterLockCount int - _ = backupConn.Get(&afterLockCount, checkLockQuery) Expect(afterLockCount).To(Equal(0)) - backupConn.MustExec("ROLLBACK") stdout := string(output) Expect(stdout).To(ContainSubstring("Received a termination signal, aborting backup process")) From 3570a0200b8ce4dbec68451e3b13ca5ced26d377 Mon Sep 17 00:00:00 2001 From: woblerr Date: Fri, 26 Jun 2026 19:05:44 +0300 Subject: [PATCH 10/10] Fix gp_segment_configuration lock e2e test. The test intended to verify that gpbackup does not keep a lock on pg_catalog.gp_segment_configuration after passing that metadata query and blocking later on pg_catalog.pg_trigger. However, the old test did not actually exercise that state: it used raw BEGIN/COMMIT SQL through DBConn, committed before gpbackup was started, queried pg_locks in an unsynchronized goroutine, and ignored query errors while scanning SELECT * into an int. Use an explicit DBConn transaction on a dedicated lock connection, start gpbackup while the pg_trigger lock is still held, wait until gpbackup is visibly blocked on pg_trigger, and then synchronously assert that no gp_segment_configuration locks remain. Finally release pg_trigger and verify gpbackup completes successfully. --- end_to_end/end_to_end_suite_test.go | 62 ++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/end_to_end/end_to_end_suite_test.go b/end_to_end/end_to_end_suite_test.go index 76a5b370..cbbfc90f 100644 --- a/end_to_end/end_to_end_suite_test.go +++ b/end_to_end/end_to_end_suite_test.go @@ -1993,7 +1993,16 @@ LANGUAGE plpgsql NO SQL;`) Skip("This test is not needed for old backup versions") } // Block on pg_trigger, which gpbackup queries after gp_segment_configuration - backupConn.MustExec("BEGIN; LOCK TABLE pg_trigger IN ACCESS EXCLUSIVE MODE") + lockConn := testutils.SetupTestDbConn("testdb") + defer lockConn.Close() + lockConn.MustBegin() + lockReleased := false + defer func() { + if !lockReleased { + _ = lockConn.Rollback() + } + }() + lockConn.MustExec("LOCK TABLE pg_catalog.pg_trigger IN ACCESS EXCLUSIVE MODE") args := []string{ "--dbname", "testdb", @@ -2001,19 +2010,54 @@ LANGUAGE plpgsql NO SQL;`) "--verbose"} cmd := exec.Command(gpbackupPath, args...) - backupConn.MustExec("COMMIT") - anotherConn := testutils.SetupTestDbConn("testdb") - defer anotherConn.Close() - var lockCount int + type commandResult struct { + output []byte + err error + } + gpbackupResultChan := make(chan commandResult, 1) go func() { - gpSegConfigQuery := `SELECT * FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND c.relname = 'gp_segment_configuration';` - _ = anotherConn.Get(&lockCount, gpSegConfigQuery) + output, err := cmd.CombinedOutput() + gpbackupResultChan <- commandResult{output: output, err: err} }() + pollConn := testutils.SetupTestDbConn("testdb") + defer pollConn.Close() + + triggerLockQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'pg_catalog' AND c.relname = 'pg_trigger' AND l.granted = 'f' AND l.mode = 'AccessShareLock'` + var gpbackupBlockedLockCount int + var earlyResult *commandResult + for iterations := 100; iterations > 0; iterations-- { + select { + case result := <-gpbackupResultChan: + earlyResult = &result + default: + } + if earlyResult != nil { + break + } + + Expect(pollConn.Get(&gpbackupBlockedLockCount, triggerLockQuery)).To(Succeed()) + if gpbackupBlockedLockCount > 0 { + break + } + time.Sleep(100 * time.Millisecond) + } + if earlyResult != nil { + Fail(fmt.Sprintf("gpbackup finished before blocking on pg_trigger: %v\n%s", earlyResult.err, string(earlyResult.output))) + } + Expect(gpbackupBlockedLockCount).To(BeNumerically(">", 0), "gpbackup did not block on pg_trigger") + + var lockCount int + gpSegConfigQuery := `SELECT count(*) FROM pg_locks l, pg_class c, pg_namespace n WHERE l.relation = c.oid AND n.oid = c.relnamespace AND n.nspname = 'pg_catalog' AND c.relname = 'gp_segment_configuration'` + Expect(pollConn.Get(&lockCount, gpSegConfigQuery)).To(Succeed()) Expect(lockCount).To(Equal(0)) - output, _ := cmd.CombinedOutput() - stdout := string(output) + lockConn.MustCommit() + lockReleased = true + + result := <-gpbackupResultChan + stdout := string(result.output) + Expect(result.err).ToNot(HaveOccurred(), "%s", stdout) Expect(stdout).To(ContainSubstring("Backup completed successfully")) }) It("properly handles various implicit casts on pg_catalog.text", func() {