diff --git a/go.mod b/go.mod index b46770609..18589def0 100644 --- a/go.mod +++ b/go.mod @@ -38,6 +38,7 @@ require ( github.com/joho/godotenv v1.5.1 github.com/mithrandie/csvq-driver v1.7.0 github.com/muesli/reflow v0.3.0 + github.com/multigres/multigres v0.0.0-20260114202706-8cdfa4159401 github.com/oapi-codegen/nullable v1.1.0 github.com/olekukonko/tablewriter v1.1.2 github.com/slack-go/slack v0.17.3 @@ -117,9 +118,10 @@ require ( github.com/butuzov/mirror v1.3.0 // indirect github.com/catenacyber/perfsprint v0.9.1 // indirect github.com/ccojocar/zxcvbn-go v1.0.2 // indirect + github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charithe/durationcheck v0.0.10 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/colorprofile v0.3.1 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/charmbracelet/x/ansi v0.10.1 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect @@ -221,7 +223,7 @@ require ( github.com/gostaticanalysis/comment v1.5.0 // indirect github.com/gostaticanalysis/forcetypeassert v0.2.0 // indirect github.com/gostaticanalysis/nilerr v0.1.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -237,7 +239,7 @@ require ( github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jgautheron/goconst v1.8.1 // indirect @@ -332,12 +334,12 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.8.0 // indirect - github.com/prometheus/client_golang v1.22.0 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.62.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect - github.com/quasilyte/go-ruleguard v0.4.4 // indirect - github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect + github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.67.4 // indirect + github.com/prometheus/procfs v0.19.2 // indirect + github.com/quasilyte/go-ruleguard v0.4.5 // indirect + github.com/quasilyte/go-ruleguard/dsl v0.3.23 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect @@ -346,7 +348,7 @@ require ( github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/ryancurrah/gomodguard v1.4.1 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect github.com/sanposhiho/wastedassign/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect @@ -362,7 +364,6 @@ require ( github.com/skeema/knownhosts v1.3.1 // indirect github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect github.com/sonatard/noctx v0.1.0 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect github.com/spf13/cast v1.10.0 // indirect @@ -407,24 +408,23 @@ require ( go-simpler.org/sloglint v0.11.0 // indirect go.augendre.info/fatcontext v0.8.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect go.opentelemetry.io/otel/metric v1.39.0 // indirect - go.opentelemetry.io/otel/sdk v1.38.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.39.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.39.0 // indirect go.opentelemetry.io/otel/trace v1.39.0 // indirect - go.opentelemetry.io/proto/otlp v1.5.0 // indirect - go.uber.org/atomic v1.9.0 // indirect + go.opentelemetry.io/proto/otlp v1.9.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - go.uber.org/zap v1.24.0 // indirect - go.yaml.in/yaml/v2 v2.4.2 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.27.0 // indirect + go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/crypto v0.47.0 // indirect golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac // indirect @@ -435,9 +435,9 @@ require ( golang.org/x/tools v0.40.0 // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda // indirect - google.golang.org/protobuf v1.36.10 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect + google.golang.org/protobuf v1.36.11 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -451,7 +451,7 @@ require ( k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect - mvdan.cc/gofumpt v0.8.0 // indirect + mvdan.cc/gofumpt v0.9.1 // indirect mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect diff --git a/go.sum b/go.sum index 1a351cc62..ed2621c05 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,6 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20150223135152-b965b613227f/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -157,6 +155,8 @@ github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= @@ -165,8 +165,8 @@ github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40= +github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0= github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -529,8 +529,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4 h1:kEISI/Gx67NzH3nJxAmY/dGac80kKZgZt134u7Y/k1s= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.4/go.mod h1:6Nz966r3vQYCqIzWsuEl9d7cf7mRhtDmm++sOxlnfxI= github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= @@ -596,8 +596,9 @@ github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwX 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/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/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= @@ -806,6 +807,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/multigres/multigres v0.0.0-20260114202706-8cdfa4159401 h1:VPySOSQmtjlhgv0R1z2JiDF0CG8z9dilYW2s68B6Mao= +github.com/multigres/multigres v0.0.0-20260114202706-8cdfa4159401/go.mod h1:UvLRTBJXqpyyXOtyEYH2NRPyklWWdzM7cNzcrEXiyRM= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -887,6 +890,8 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= +github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls= +github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= @@ -909,28 +914,28 @@ github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= +github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/common v0.67.4 h1:yR3NqWO1/UyO1w2PhUvXlGQs/PtFmoveVO0KZ4+Lvsc= +github.com/prometheus/common v0.67.4/go.mod h1:gP0fq6YjjNCLssJCQp0yk4M8W6ikLURwkdd/YKtTbyI= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/quasilyte/go-ruleguard v0.4.4 h1:53DncefIeLX3qEpjzlS1lyUmQoUEeOWPFWqaTJq9eAQ= -github.com/quasilyte/go-ruleguard v0.4.4/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= -github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= +github.com/quasilyte/go-ruleguard v0.4.5 h1:AGY0tiOT5hJX9BTdx/xBdoCubQUAE2grkqY2lSwvZcA= +github.com/quasilyte/go-ruleguard v0.4.5/go.mod h1:Vl05zJ538vcEEwu16V/Hdu7IYZWyKSwIy4c88Ro1kRE= +github.com/quasilyte/go-ruleguard/dsl v0.3.23 h1:lxjt5B6ZCiBeeNO8/oQsegE6fLeCzuMRoVWSkXC4uvY= +github.com/quasilyte/go-ruleguard/dsl v0.3.23/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= @@ -955,8 +960,8 @@ github.com/ryancurrah/gomodguard v1.4.1 h1:eWC8eUMNZ/wM/PWuZBv7JxxqT5fiIKSIyTvjb github.com/ryancurrah/gomodguard v1.4.1/go.mod h1:qnMJwV1hX9m+YJseXEBhd2s90+1Xn6x9dLz11ualI1I= github.com/ryanrolds/sqlclosecheck v0.5.1 h1:dibWW826u0P8jNLsLN+En7+RqWWTYrjCB9fJfSfdyCU= github.com/ryanrolds/sqlclosecheck v0.5.1/go.mod h1:2g3dUjoS6AL4huFdv6wn55WpLIDjY7ZgUR4J8HOO/XQ= -github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4= +github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sanposhiho/wastedassign/v2 v2.1.0 h1:crurBF7fJKIORrV85u9UUpePDYGWnwvv3+A96WvwXT0= @@ -1001,8 +1006,6 @@ github.com/slack-go/slack v0.17.3 h1:zV5qO3Q+WJAQ/XwbGfNFrRMaJ5T/naqaonyPV/1TP4g github.com/slack-go/slack v0.17.3/go.mod h1:X+UqOufi3LYQHDnMG1vxf0J8asC6+WllXrVrhl8/Prk= github.com/sonatard/noctx v0.1.0 h1:JjqOc2WN16ISWAjAk8M5ej0RfExEXtkEyExl2hLW+OM= github.com/sonatard/noctx v0.1.0/go.mod h1:0RvBxqY8D4j9cTTTWE8ylt2vqj2EPI8fHmrxHdsaZ2c= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk= @@ -1156,40 +1159,38 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 h1:RN3ifU8y4prNWeEnQp2kRRHz8UwonAEYZl8tUzHEXAk= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0/go.mod h1:habDz3tEWiFANTo6oUE99EmaFUrCNYAAg3wiVmusm70= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 h1:0tY123n7CdWMem7MOVdKOt0YfshufLCwfE5Bob+hQuM= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0/go.mod h1:CosX/aS4eHnG9D7nESYpV753l4j9q5j3SL/PUYd2lR8= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 h1:0NIXxOCFx+SKbhCVxwl3ETG8ClLPAa0KuKV6p3yhxP8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0/go.mod h1:ChZSJbbfbl/DcRZNc9Gqh6DYGlfjw4PvO1pEOZH1ZsE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0 h1:cEf8jF6WbuGQWUVcqgyWtTR0kOOAWY1DYZ+UhvdmQPw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.39.0/go.mod h1:k1lzV5n5U3HkGvTCJHraTAGJ7MqsgL1wrGwTj1Isfiw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.39.0 h1:nKP4Z2ejtHn3yShBb+2KawiXgpn8In5cT7aO2wXuOTE= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.39.0/go.mod h1:NwjeBbNigsO4Aj9WgM0C+cKIrxsZUaRmZUO7A8I7u8o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0 h1:in9O8ESIOlwJAEGTkkf34DesGRAc/Pn8qJ7k3r/42LM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.39.0/go.mod h1:Rp0EXBm5tfnv0WL+ARyO/PHBEaEAT8UUHQ6AGJcSq6c= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU= go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= -go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= -go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= -go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= -go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= -go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= -go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= +go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= 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/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -1199,16 +1200,16 @@ go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= 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/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 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.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI= -go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +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= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1232,8 +1233,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= +golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= +golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= @@ -1413,10 +1414,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE= -google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda h1:i/Q+bfisr7gq6feoJnS/DlpdwEL4ihp41fvRiM3Ork0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251029180050-ab9386a59fda/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E= +google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= @@ -1428,8 +1429,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi 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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= -google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII= @@ -1486,8 +1487,8 @@ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJ k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= -mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= +mvdan.cc/gofumpt v0.9.1 h1:p5YT2NfFWsYyTieYgwcQ8aKV3xRvFH4uuN/zB2gBbMQ= +mvdan.cc/gofumpt v0.9.1/go.mod h1:3xYtNemnKiXaTh6R4VtlqDATFwBbdXI8lJvH/4qk7mw= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE= sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8= diff --git a/internal/db/pull/pull.go b/internal/db/pull/pull.go index b55b6935c..93ef5450e 100644 --- a/internal/db/pull/pull.go +++ b/internal/db/pull/pull.go @@ -1,6 +1,7 @@ package pull import ( + "bytes" "context" _ "embed" "fmt" @@ -14,8 +15,10 @@ import ( "github.com/jackc/pgconn" "github.com/jackc/pgx/v4" "github.com/spf13/afero" + "github.com/spf13/viper" "github.com/supabase/cli/internal/db/diff" "github.com/supabase/cli/internal/db/dump" + "github.com/supabase/cli/internal/migration/format" "github.com/supabase/cli/internal/migration/list" "github.com/supabase/cli/internal/migration/new" "github.com/supabase/cli/internal/migration/repair" @@ -36,6 +39,14 @@ func Run(ctx context.Context, schema []string, config pgconn.Config, name string return err } defer conn.Close(context.Background()) + if viper.GetBool("EXPERIMENTAL") { + var buf bytes.Buffer + if err := migration.DumpSchema(ctx, config, &buf, dump.DockerExec); err != nil { + return err + } + // TODO: handle managed schemas + return format.WriteStructuredSchemas(ctx, buf.String(), fsys) + } // 2. Pull schema timestamp := utils.GetCurrentTimestamp() path := new.GetMigrationPath(timestamp, name) diff --git a/internal/migration/format/format.go b/internal/migration/format/format.go new file mode 100644 index 000000000..1df5e7331 --- /dev/null +++ b/internal/migration/format/format.go @@ -0,0 +1,394 @@ +package format + +import ( + "context" + _ "embed" + "fmt" + "os" + "path/filepath" + + "github.com/go-errors/errors" + "github.com/multigres/multigres/go/parser" + "github.com/multigres/multigres/go/parser/ast" + "github.com/spf13/afero" + "github.com/supabase/cli/internal/utils" +) + +//go:embed templates/order.toml +var order string + +func WriteStructuredSchemas(ctx context.Context, sql string, fsys afero.Fs) error { + stat, err := parser.ParseSQL(sql) + if err != nil { + return errors.Errorf("failed to parse SQL: %w", err) + } + for _, d := range []string{utils.ClusterDir, utils.SchemasDir, utils.DataDir} { + if err := fsys.RemoveAll(d); err != nil { + return errors.Errorf("failed to remove directory: %w", err) + } + } + for _, s := range stat { + name := utils.UnqualifiedPath + switch v := s.(type) { + // Cluster level entities + case *ast.CreateRoleStmt, *ast.AlterRoleStmt, *ast.AlterRoleSetStmt, *ast.GrantRoleStmt: + name = utils.RolesPath + case *ast.CreateExtensionStmt, *ast.AlterExtensionStmt, *ast.AlterExtensionContentsStmt: + name = utils.ExtensionsPath + case *ast.CreateFdwStmt, *ast.AlterFdwStmt, *ast.CreateForeignServerStmt, *ast.AlterForeignServerStmt, *ast.CreateUserMappingStmt, *ast.AlterUserMappingStmt: + name = utils.ForeignDWPath + case *ast.CreatePublicationStmt, *ast.AlterPublicationStmt: + name = utils.PublicationsPath + case *ast.CreateSubscriptionStmt, *ast.AlterSubscriptionStmt: + name = utils.SubscriptionsPath + case *ast.CreateEventTrigStmt, *ast.AlterEventTrigStmt: + name = utils.EventTriggersPath + case *ast.CreateTableSpaceStmt, *ast.AlterTableSpaceStmt: + name = utils.TablespacesPath + case *ast.AlterDatabaseStmt, *ast.AlterDatabaseSetStmt, *ast.AlterSystemStmt, *ast.VariableSetStmt: + name = utils.VariablesPath + // Schema level entities + case *ast.CreateSchemaStmt: + name = getSchemaPath(v.Schemaname) + case *ast.CreateOpFamilyStmt: + if s := getQualifiedSchema(v.OpFamilyName); s != nil { + name = getSchemaPath(s.SVal) + } + case *ast.AlterOpFamilyStmt: + if s := getQualifiedSchema(v.OpFamilyName); s != nil { + name = getSchemaPath(s.SVal) + } + case *ast.AlterCollationStmt: + if s := getQualifiedSchema(v.Collname); s != nil { + name = getSchemaPath(s.SVal) + } + case *ast.AlterTSDictionaryStmt: + if s := getQualifiedSchema(v.Dictname); s != nil { + name = getSchemaPath(s.SVal) + } + case *ast.AlterTSConfigurationStmt: + if s := getQualifiedSchema(v.Cfgname); s != nil { + name = getSchemaPath(s.SVal) + } + // Schema level entities - types + case *ast.CompositeTypeStmt: + if r := v.Typevar; r != nil && len(r.SchemaName) > 0 { + name = getTypesPath(r.SchemaName) + } + case *ast.AlterCompositeTypeStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.AlterTypeStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.CreateEnumStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.AlterEnumStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.CreateRangeStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.CreateTransformStmt: + if t := v.TypeName; t != nil { + if s := getQualifiedSchema(t.Names); s != nil { + name = getTypesPath(s.SVal) + } + } + case *ast.CreateDomainStmt: + if s := getQualifiedSchema(v.Domainname); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.AlterDomainStmt: + if s := getQualifiedSchema(v.TypeName); s != nil { + name = getTypesPath(s.SVal) + } + case *ast.CreateOpClassStmt: + if t := v.DataType; t != nil { + if s := getQualifiedSchema(t.Names); s != nil { + name = getTypesPath(s.SVal) + } + } + case *ast.DefineStmt: + if s := getQualifiedSchema(v.DefNames); s != nil { + name = getTypesPath(s.SVal) + } + // Schema level entities - relations + case *ast.CreateStmt: + if r := v.Relation; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + case *ast.AlterTableStmt: + if r := v.Relation; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + case *ast.CreateForeignTableStmt: + if t := v.Base; t != nil { + if r := t.Relation; r != nil && len(r.SchemaName) > 0 { + name = getForeignTablePath(r.SchemaName, r.RelName) + } + } + case *ast.CreateTableAsStmt: + if t := v.Into; t != nil { + if r := t.Rel; r != nil && len(r.SchemaName) > 0 { + name = getMaterializedViewPath(r.SchemaName, r.RelName) + } + } + case *ast.ViewStmt: + if r := v.View; r != nil && len(r.SchemaName) > 0 { + name = getViewPath(r.SchemaName, r.RelName) + } + case *ast.CreateSeqStmt: + if r := v.Sequence; r != nil && len(r.SchemaName) > 0 { + name = getSequencesPath(r.SchemaName) + } + case *ast.AlterSeqStmt: + if r := v.Sequence; r != nil && len(r.SchemaName) > 0 { + name = getSequencesPath(r.SchemaName) + } + case *ast.IndexStmt: + if r := v.Relation; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + case *ast.CreatePolicyStmt: + if r := v.Table; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + case *ast.AlterPolicyStmt: + if r := v.Table; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + case *ast.RuleStmt: + if r := v.Relation; r != nil && len(r.SchemaName) > 0 { + name = getTablePath(r.SchemaName, r.RelName) + } + // Schema level entities - functions + case *ast.CreateFunctionStmt: + if s := toQualifiedName(v.FuncName); len(s) == 2 { + name = getFunctionPath(s[0], s[1]) + } + case *ast.AlterFunctionStmt: + if f := v.Func; f != nil { + if s := toQualifiedName(f.Objname); len(s) == 2 { + name = getFunctionPath(s[0], s[1]) + } + } + case *ast.CreateTriggerStmt: + if s := toQualifiedName(v.Funcname); len(s) == 2 { + name = getFunctionPath(s[0], s[1]) + } + case *ast.CreatePLangStmt: + if s := toQualifiedName(v.PLHandler); len(s) == 2 { + name = getFunctionPath(s[0], s[1]) + } + case *ast.CreateAmStmt: + if s := toQualifiedName(v.HandlerName); len(s) == 2 { + name = getFunctionPath(s[0], s[1]) + } + // Schema level entities - others + case *ast.CommentStmt: + if s := getNodePath(v.Objtype, v.Object); len(s) > 0 { + name = s + } + case *ast.AlterOwnerStmt: + if s := getNodePath(v.ObjectType, v.Object); len(s) > 0 { + name = s + } + case *ast.GrantStmt: + if n := v.Objects; n != nil && len(n.Items) == 1 { + if s := getNodePath(v.Objtype, n.Items[0]); len(s) > 0 { + name = s + } + } + case *ast.AlterDefaultPrivilegesStmt: + if n := v.Options; n != nil { + for _, s := range n.Items { + if e, ok := s.(*ast.DefElem); ok && e.Defname == "schemas" { + if n, ok := e.Arg.(*ast.NodeList); ok && len(n.Items) == 1 { + if p, ok := n.Items[0].(*ast.String); ok { + name = getPrivilegesPath(p.SVal) + } + } + } + } + } + // TODO: Data level entities, ie. pg_cron, pgmq, etc. + case *ast.InsertStmt, *ast.UpdateStmt, *ast.DeleteStmt, *ast.CopyStmt, *ast.CallStmt, *ast.SelectStmt: + } + if name == utils.UnqualifiedPath { + fmt.Fprintln(os.Stderr, "Unsupported:", s.SqlString()) + } + if err := appendFile(name, s.SqlString()+";\n", fsys); err != nil { + return err + } + } + if len(utils.Config.Db.Migrations.SchemaPaths) == 0 { + return appendFile(utils.ConfigPath, order, fsys) + } + return nil +} + +func getNodePath(obj ast.ObjectType, n ast.Node) string { + switch obj { + case ast.OBJECT_ACCESS_METHOD: + case ast.OBJECT_AGGREGATE: + // case ast.OBJECT_AMOP: + // case ast.OBJECT_AMPROC: + // case ast.OBJECT_ATTRIBUTE: + // case ast.OBJECT_CAST: + case ast.OBJECT_COLUMN: + case ast.OBJECT_COLLATION: + // case ast.OBJECT_CONVERSION: + // case ast.OBJECT_DATABASE: + // case ast.OBJECT_DEFAULT: + // case ast.OBJECT_DEFACL: + case ast.OBJECT_DOMAIN: + // case ast.OBJECT_DOMCONSTRAINT: + case ast.OBJECT_EVENT_TRIGGER: + return utils.EventTriggersPath + case ast.OBJECT_EXTENSION: + return utils.ExtensionsPath + case ast.OBJECT_FDW: + return utils.ForeignDWPath + case ast.OBJECT_FOREIGN_SERVER: + return utils.ForeignDWPath + case ast.OBJECT_FOREIGN_TABLE: + case ast.OBJECT_FUNCTION: + case ast.OBJECT_INDEX: + // case ast.OBJECT_LANGUAGE: + // case ast.OBJECT_LARGEOBJECT: + case ast.OBJECT_MATVIEW: + // case ast.OBJECT_OPCLASS: + // case ast.OBJECT_OPERATOR: + // case ast.OBJECT_OPFAMILY: + // case ast.OBJECT_PARAMETER_ACL: + case ast.OBJECT_POLICY: + case ast.OBJECT_PROCEDURE: + case ast.OBJECT_PUBLICATION: + return utils.PublicationsPath + case ast.OBJECT_PUBLICATION_NAMESPACE: + case ast.OBJECT_PUBLICATION_REL: + case ast.OBJECT_ROLE: + case ast.OBJECT_ROUTINE: + case ast.OBJECT_RULE: + case ast.OBJECT_SCHEMA: + if s, ok := n.(*ast.String); ok { + return getSchemaPath(s.SVal) + } + case ast.OBJECT_SEQUENCE: + if nl, ok := n.(*ast.NodeList); ok { + if s := toQualifiedName(nl); len(s) == 2 { + return getTablePath(s[0], s[1]) + } + } else if s, ok := n.(*ast.RangeVar); ok { + return getSequencesPath(s.SchemaName) + } + case ast.OBJECT_SUBSCRIPTION: + return utils.SubscriptionsPath + // case ast.OBJECT_STATISTIC_EXT: + // case ast.OBJECT_TABCONSTRAINT: + case ast.OBJECT_TABLE: + if nl, ok := n.(*ast.NodeList); ok { + if s := toQualifiedName(nl); len(s) == 2 { + return getTablePath(s[0], s[1]) + } + } else if r, ok := n.(*ast.RangeVar); ok && len(r.SchemaName) > 0 { + return getTablePath(r.SchemaName, r.RelName) + } + case ast.OBJECT_TABLESPACE: + case ast.OBJECT_TRANSFORM: + case ast.OBJECT_TRIGGER: + case ast.OBJECT_TSCONFIGURATION: + case ast.OBJECT_TSDICTIONARY: + // case ast.OBJECT_TSPARSER: + // case ast.OBJECT_TSTEMPLATE: + case ast.OBJECT_TYPE: + if nl, ok := n.(*ast.NodeList); ok && len(nl.Items) == 2 { + if s, ok := nl.Items[0].(*ast.String); ok { + return getTypesPath(s.SVal) + } + } + case ast.OBJECT_USER_MAPPING: + case ast.OBJECT_VIEW: + } + return "" +} + +func getQualifiedSchema(n *ast.NodeList) *ast.String { + if n != nil && len(n.Items) == 2 { + if s, ok := n.Items[0].(*ast.String); ok { + return s + } + } + return nil +} + +func toQualifiedName(n *ast.NodeList) []string { + if n == nil { + return nil + } + var r []string + for _, v := range n.Items { + if s, ok := v.(*ast.String); ok { + r = append(r, s.SVal) + } + } + return r +} + +func getSchemaPath(name string) string { + return filepath.Join(utils.SchemasDir, name, "schema.sql") +} + +func getTypesPath(schema string) string { + return filepath.Join(utils.SchemasDir, schema, "types.sql") +} + +func getSequencesPath(schema string) string { + return filepath.Join(utils.SchemasDir, schema, "sequences.sql") +} + +func getPrivilegesPath(schema string) string { + return filepath.Join(utils.SchemasDir, schema, "privileges.sql") +} + +func getTablePath(schema, name string) string { + return filepath.Join(utils.SchemasDir, schema, "tables", name+".sql") +} + +func getForeignTablePath(schema, name string) string { + return filepath.Join(utils.SchemasDir, schema, "foreign_tables", name+".sql") +} + +func getFunctionPath(schema, name string) string { + return filepath.Join(utils.SchemasDir, schema, "functions", name+".sql") +} + +func getMaterializedViewPath(schema, name string) string { + return filepath.Join(utils.SchemasDir, schema, "materialized_views", name+".sql") +} + +func getViewPath(schema, name string) string { + return filepath.Join(utils.SchemasDir, schema, "views", name+".sql") +} + +func appendFile(name, data string, fsys afero.Fs) error { + if err := utils.MkdirIfNotExistFS(fsys, filepath.Dir(name)); err != nil { + return err + } + f, err := fsys.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) + if err != nil { + return errors.Errorf("failed to open file: %w", err) + } + defer f.Close() + if _, err := f.WriteString(data); err != nil { + return errors.Errorf("failed to write file: %w", err) + } + return nil +} diff --git a/internal/migration/format/format_test.go b/internal/migration/format/format_test.go new file mode 100644 index 000000000..a2feb856c --- /dev/null +++ b/internal/migration/format/format_test.go @@ -0,0 +1,59 @@ +package format + +import ( + "context" + "embed" + "fmt" + "io/fs" + "path" + "testing" + + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/supabase/cli/internal/utils" +) + +//go:embed testdata +var testdata embed.FS + +func TestWriteStructured(t *testing.T) { + testCases, err := testdata.ReadDir("testdata") + require.NoError(t, err) + + for _, tc := range testCases { + testName := fmt.Sprintf("formats %s statements", tc.Name()) + testFs := afero.NewBasePathFs( + afero.FromIOFS{FS: testdata}, + path.Join("testdata", tc.Name()), + ) + const dumpPath = "dump.sql" + + t.Run(testName, func(t *testing.T) { + sql, err := afero.ReadFile(testFs, dumpPath) + assert.NoError(t, err) + // Setup in-memory fs + fsys := afero.NewMemMapFs() + // Run test + err = WriteStructuredSchemas(context.Background(), string(sql), fsys) + // Check error + assert.NoError(t, err) + err = afero.Walk(testFs, ".", func(fp string, info fs.FileInfo, err error) error { + if err != nil || info.IsDir() || info.Name() == dumpPath { + return err + } + expected, err := afero.ReadFile(testFs, fp) + if err != nil { + return err + } + actual, err := afero.ReadFile(fsys, path.Join(utils.SupabaseDirPath, fp)) + if err != nil { + return err + } + assert.Equal(t, string(expected), string(actual), fp) + return nil + }) + assert.NoError(t, err) + }) + } +} diff --git a/internal/migration/format/templates/order.toml b/internal/migration/format/templates/order.toml new file mode 100644 index 000000000..a0f3e9f81 --- /dev/null +++ b/internal/migration/format/templates/order.toml @@ -0,0 +1,35 @@ +[db.migrations] +schema_paths = [ + # 1. Cluster-level objects + "./cluster/roles.sql", + "./cluster/extensions.sql", + "./cluster/foreign_data_wrappers.sql", + + # 2. Schema definitions + "./schemas/*/schema.sql", + + # 3. Types and sequences (before tables) + "./schemas/*/types.sql", + "./schemas/*/sequences.sql", + + # 4. Tables (with indexes, constraints) + "./schemas/*/tables/*.sql", + + # 5. Foreign tables + "./schemas/*/foreign_tables/*.sql", + + # 6. Views and materialized views (depend on tables) + "./schemas/*/views/*.sql", + "./schemas/*/materialized_views/*.sql", + + # 7. Functions and procedures (scalar/table-valued only; trigger functions are with their tables/views) + "./schemas/*/functions/*.sql", + "./schemas/*/procedures/*.sql", + + # 8. Replication (depends on tables) + "./cluster/publications.sql", + "./cluster/subscriptions.sql", + + # 9. Event triggers (last) + "./cluster/event_triggers.sql", +] diff --git a/internal/migration/format/testdata/simple/cluster/extensions.sql b/internal/migration/format/testdata/simple/cluster/extensions.sql new file mode 100644 index 000000000..120fecd6d --- /dev/null +++ b/internal/migration/format/testdata/simple/cluster/extensions.sql @@ -0,0 +1,8 @@ +CREATE EXTENSION IF NOT EXISTS pgsodium; +CREATE EXTENSION IF NOT EXISTS pg_graphql SCHEMA graphql; +CREATE EXTENSION IF NOT EXISTS pg_stat_statements SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS pgjwt SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS postgis SCHEMA extensions; +CREATE EXTENSION IF NOT EXISTS supabase_vault SCHEMA vault; +CREATE EXTENSION IF NOT EXISTS uuid-ossp SCHEMA extensions; diff --git a/internal/migration/format/testdata/simple/cluster/publications.sql b/internal/migration/format/testdata/simple/cluster/publications.sql new file mode 100644 index 000000000..57d298ec0 --- /dev/null +++ b/internal/migration/format/testdata/simple/cluster/publications.sql @@ -0,0 +1 @@ +ALTER PUBLICATION supabase_realtime OWNER TO postgres; diff --git a/internal/migration/format/testdata/simple/cluster/variables.sql b/internal/migration/format/testdata/simple/cluster/variables.sql new file mode 100644 index 000000000..a475757af --- /dev/null +++ b/internal/migration/format/testdata/simple/cluster/variables.sql @@ -0,0 +1,11 @@ +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET NAMES 'UTF8'; +SET standard_conforming_strings = on; +SET check_function_bodies = false; +SET XML OPTION CONTENT; +SET client_min_messages = 'warning'; +SET row_security = off; +SET default_tablespace = ''; +SET default_table_access_method = 'heap'; diff --git a/internal/migration/format/testdata/simple/dump.sql b/internal/migration/format/testdata/simple/dump.sql new file mode 100644 index 000000000..465653e43 --- /dev/null +++ b/internal/migration/format/testdata/simple/dump.sql @@ -0,0 +1,73 @@ +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; +CREATE EXTENSION IF NOT EXISTS "pgsodium"; +COMMENT ON SCHEMA "public" IS 'standard public schema'; +CREATE EXTENSION IF NOT EXISTS "pg_graphql" WITH SCHEMA "graphql"; +CREATE EXTENSION IF NOT EXISTS "pg_stat_statements" WITH SCHEMA "extensions"; +CREATE EXTENSION IF NOT EXISTS "pgcrypto" WITH SCHEMA "extensions"; +CREATE EXTENSION IF NOT EXISTS "pgjwt" WITH SCHEMA "extensions"; +CREATE EXTENSION IF NOT EXISTS "postgis" WITH SCHEMA "extensions"; +CREATE EXTENSION IF NOT EXISTS "supabase_vault" WITH SCHEMA "vault"; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp" WITH SCHEMA "extensions"; +CREATE TYPE "public"."continents" AS ENUM ( + 'Africa', + 'Antarctica', + 'Asia', + 'Europe', + 'Oceania', + 'North America', + 'South America' +); +ALTER TYPE "public"."continents" OWNER TO "postgres"; +SET default_tablespace = ''; +SET default_table_access_method = "heap"; +CREATE TABLE IF NOT EXISTS "public"."countries" ( + "id" bigint NOT NULL, + "name" "text", + "iso2" "text" NOT NULL, + "iso3" "text", + "local_name" "text", + "continent" "public"."continents" +); +ALTER TABLE "public"."countries" OWNER TO "postgres"; +ALTER TABLE "public"."countries" ALTER COLUMN "id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME "public"."countries_id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); +ALTER TABLE ONLY "public"."countries" + ADD CONSTRAINT "countries_pkey" PRIMARY KEY ("id"); +ALTER PUBLICATION "supabase_realtime" OWNER TO "postgres"; +GRANT USAGE ON SCHEMA "public" TO "postgres"; +GRANT USAGE ON SCHEMA "public" TO "anon"; +GRANT USAGE ON SCHEMA "public" TO "authenticated"; +GRANT USAGE ON SCHEMA "public" TO "service_role"; +GRANT ALL ON TABLE "public"."countries" TO "anon"; +GRANT ALL ON TABLE "public"."countries" TO "authenticated"; +GRANT ALL ON TABLE "public"."countries" TO "service_role"; +GRANT ALL ON SEQUENCE "public"."countries_id_seq" TO "anon"; +GRANT ALL ON SEQUENCE "public"."countries_id_seq" TO "authenticated"; +GRANT ALL ON SEQUENCE "public"."countries_id_seq" TO "service_role"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON SEQUENCES TO "service_role"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON FUNCTIONS TO "service_role"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "postgres"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "anon"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "authenticated"; +ALTER DEFAULT PRIVILEGES FOR ROLE "postgres" IN SCHEMA "public" GRANT ALL ON TABLES TO "service_role"; diff --git a/internal/migration/format/testdata/simple/schemas/public/privileges.sql b/internal/migration/format/testdata/simple/schemas/public/privileges.sql new file mode 100644 index 000000000..acd9f926c --- /dev/null +++ b/internal/migration/format/testdata/simple/schemas/public/privileges.sql @@ -0,0 +1,12 @@ +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO postgres; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO anon; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO authenticated; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO service_role; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO postgres; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO anon; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO authenticated; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO service_role; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO postgres; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO anon; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO authenticated; +ALTER DEFAULT PRIVILEGES FOR ROLE postgres IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO service_role; diff --git a/internal/migration/format/testdata/simple/schemas/public/schema.sql b/internal/migration/format/testdata/simple/schemas/public/schema.sql new file mode 100644 index 000000000..dab5a9436 --- /dev/null +++ b/internal/migration/format/testdata/simple/schemas/public/schema.sql @@ -0,0 +1,5 @@ +COMMENT ON SCHEMA public IS 'standard public schema'; +GRANT USAGE ON SCHEMA public TO postgres; +GRANT USAGE ON SCHEMA public TO anon; +GRANT USAGE ON SCHEMA public TO authenticated; +GRANT USAGE ON SCHEMA public TO service_role; diff --git a/internal/migration/format/testdata/simple/schemas/public/sequences.sql b/internal/migration/format/testdata/simple/schemas/public/sequences.sql new file mode 100644 index 000000000..8123ca0fd --- /dev/null +++ b/internal/migration/format/testdata/simple/schemas/public/sequences.sql @@ -0,0 +1,3 @@ +GRANT ALL ON SEQUENCE public.countries_id_seq TO anon; +GRANT ALL ON SEQUENCE public.countries_id_seq TO authenticated; +GRANT ALL ON SEQUENCE public.countries_id_seq TO service_role; diff --git a/internal/migration/format/testdata/simple/schemas/public/tables/countries.sql b/internal/migration/format/testdata/simple/schemas/public/tables/countries.sql new file mode 100644 index 000000000..c64ea7ba7 --- /dev/null +++ b/internal/migration/format/testdata/simple/schemas/public/tables/countries.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS public.countries (id BIGINT NOT NULL, name TEXT, iso2 TEXT NOT NULL, iso3 TEXT, local_name TEXT, continent continents); +ALTER TABLE public.countries OWNER TO postgres; +ALTER TABLE public.countries ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1 CACHE 1); +ALTER TABLE ONLY public.countries ADD CONSTRAINT countries_pkey PRIMARY KEY (id); +GRANT ALL ON public.countries TO anon; +GRANT ALL ON public.countries TO authenticated; +GRANT ALL ON public.countries TO service_role; diff --git a/internal/migration/format/testdata/simple/schemas/public/types.sql b/internal/migration/format/testdata/simple/schemas/public/types.sql new file mode 100644 index 000000000..b9020d1ce --- /dev/null +++ b/internal/migration/format/testdata/simple/schemas/public/types.sql @@ -0,0 +1,2 @@ +CREATE TYPE public.continents AS ENUM ('Africa', 'Antarctica', 'Asia', 'Europe', 'Oceania', 'North America', 'South America'); +ALTER TYPE public.continents OWNER TO postgres; diff --git a/internal/utils/misc.go b/internal/utils/misc.go index b47a8a3eb..9fb6ed265 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -77,7 +77,18 @@ var ( CliVersionPath = filepath.Join(TempDir, "cli-latest") ProfilePath = filepath.Join(TempDir, "profile") CurrBranchPath = filepath.Join(SupabaseDirPath, ".branches", "_current_branch") + ClusterDir = filepath.Join(SupabaseDirPath, "cluster") + RolesPath = filepath.Join(ClusterDir, "roles.sql") + ExtensionsPath = filepath.Join(ClusterDir, "extensions.sql") + ForeignDWPath = filepath.Join(ClusterDir, "foreign_data_wrappers.sql") + PublicationsPath = filepath.Join(ClusterDir, "publications.sql") + SubscriptionsPath = filepath.Join(ClusterDir, "subscriptions.sql") + EventTriggersPath = filepath.Join(ClusterDir, "event_triggers.sql") + TablespacesPath = filepath.Join(ClusterDir, "tablespaces.sql") + VariablesPath = filepath.Join(ClusterDir, "variables.sql") SchemasDir = filepath.Join(SupabaseDirPath, "schemas") + UnqualifiedPath = filepath.Join(SchemasDir, "unqualified.sql") + DataDir = filepath.Join(SupabaseDirPath, "data") MigrationsDir = filepath.Join(SupabaseDirPath, "migrations") FunctionsDir = filepath.Join(SupabaseDirPath, "functions") SnippetsDir = filepath.Join(SupabaseDirPath, "snippets")