diff --git a/go.mod b/go.mod index 61bcb400..28df9a68 100644 --- a/go.mod +++ b/go.mod @@ -97,7 +97,7 @@ require ( github.com/mschoch/smat v0.2.0 // indirect github.com/nacos-group/nacos-sdk-go v1.1.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pelletier/go-toml v1.7.0 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect github.com/pelletier/go-toml/v2 v2.0.1 // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63 // indirect @@ -115,11 +115,11 @@ require ( github.com/shirou/gopsutil/v3 v3.22.2 // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/afero v1.2.2 // indirect - github.com/spf13/cast v1.3.0 // indirect - github.com/spf13/jwalterweatherman v1.0.0 // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/spf13/viper v1.7.1 // indirect + github.com/spf13/viper v1.8.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect @@ -141,7 +141,7 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220630174209-ad1d48641aa7 // indirect - gopkg.in/ini.v1 v1.51.0 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 8f2d8084..29acf892 100644 --- a/go.sum +++ b/go.sum @@ -90,9 +90,6 @@ github.com/apache/dubbo-go-hessian2 v1.11.0 h1:VTdT6NStuEqNmyT3AdSN2DLDBqhXvAAyA github.com/apache/dubbo-go-hessian2 v1.11.0/go.mod h1:7rEw9guWABQa6Aqb8HeZcsYPHsOS7XT1qtJvkmI6c5w= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.1-0.20201008052519-daf620915714/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/appleboy/gin-jwt/v2 v2.6.3/go.mod h1:MfPYA4ogzvOcVkRwAxT7quHOtQmVKDpTwxyUrC2DNw0= -github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw= github.com/arana-db/parser v0.2.5 h1:X7SZUjs52nNkX+PL3wrJVd7+BL4VALIXahX+Bx+pmOQ= github.com/arana-db/parser v0.2.5/go.mod h1:/XA29bplweWSEAjgoM557ZCzhBilSawUlHcZFjOeDAc= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -124,6 +121,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= @@ -533,6 +531,7 @@ github.com/knadh/koanf v1.4.1/go.mod h1:1cfH5223ZeZUOs8FU2UdTmaNfHpqgtjV0+NHjRO4 github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7/go.mod h1:Y2SaZf2Rzd0pXkLVhLlCiAXFCLSXAIbTKDivVgff/AM= 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.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -554,6 +553,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -646,8 +646,9 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= @@ -668,6 +669,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polarismesh/polaris-go v1.0.2 h1:vMPTgO+DKNq9mC5HP7wFnlotIqg2waOAIKQq0qoZchY= @@ -765,21 +767,25 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 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/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stephens2424/writerset v1.0.2/go.mod h1:aS2JhsMn6eA7e82oNmW4rfsgAOp9COBTTl8mzkwADnc= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -846,12 +852,15 @@ go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd/api/v3 v3.5.0-alpha.0/go.mod h1:mPcW6aZJukV6Aa81LSKpBjQXTWlXB5r74ymPoSWa3Sw= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0-alpha.0 h1:jZepGpOeJATxsbMNBZczDS2jHdK/QVHM1iPe9jURJ8o= go.etcd.io/etcd/client/v2 v2.305.0-alpha.0/go.mod h1:kdV+xzCJ3luEBSIeQyB/OEKkWKd8Zkux4sbDeANrosU= +go.etcd.io/etcd/client/v2 v2.305.0 h1:ftQ0nOOHMcbMS3KIaDQ0g5Qcd6bhaBrQT6b89DfwLTs= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v3 v3.5.0-alpha.0/go.mod h1:wKt7jgDgf/OfKiYmCq5WFGxOFAkVMLxiiXgLDFhECr8= go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= @@ -907,6 +916,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1020,6 +1030,7 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1237,6 +1248,7 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1379,8 +1391,9 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= @@ -1410,8 +1423,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254= modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk= @@ -1425,7 +1436,6 @@ modernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtx modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= modernc.org/y v1.0.1/go.mod h1:Ho86I+LVHEI+LYXoUKlmOMAM1JTXOCfj8qi1T8PsClE= -moul.io/zapgorm2 v1.1.0/go.mod h1:emRfKjNqSzVj5lcgasBdovIXY1jSOwFz2GQZn1Rddks= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/pkg/common/reflectx/reflect.go b/pkg/common/reflectx/reflect.go new file mode 100644 index 00000000..5f844af7 --- /dev/null +++ b/pkg/common/reflectx/reflect.go @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package reflectx + +import ( + "reflect" + "unsafe" +) + +func SetUnexportedField(field reflect.Value, value interface{}) { + reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())). + Elem(). + Set(reflect.ValueOf(value)) +} + +func GetUnexportedField(field reflect.Value) interface{} { + return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Interface() +} diff --git a/pkg/datasource/sql/conn.go b/pkg/datasource/sql/conn.go index ceb1a8ed..862c7790 100644 --- a/pkg/datasource/sql/conn.go +++ b/pkg/datasource/sql/conn.go @@ -111,6 +111,7 @@ func (c *Conn) Exec(query string, args []driver.Value) (driver.Result, error) { TxCtx: c.txCtx, Query: query, Values: args, + Conn: c.targetConn, } return executor.ExecWithValue(context.Background(), execCtx, @@ -153,6 +154,7 @@ func (c *Conn) ExecContext(ctx context.Context, query string, args []driver.Name TxCtx: c.txCtx, Query: query, NamedValues: args, + Conn: c.targetConn, } ret, err := executor.ExecWithNamedValue(ctx, execCtx, diff --git a/pkg/datasource/sql/conn_xa_test.go b/pkg/datasource/sql/conn_xa_test.go index 198a7dd6..d668b586 100644 --- a/pkg/datasource/sql/conn_xa_test.go +++ b/pkg/datasource/sql/conn_xa_test.go @@ -43,17 +43,19 @@ func (mi *mockSQLInterceptor) Type() types.SQLType { } // Before -func (mi *mockSQLInterceptor) Before(ctx context.Context, execCtx *exec.ExecContext) { +func (mi *mockSQLInterceptor) Before(ctx context.Context, execCtx *exec.ExecContext) error { if mi.before != nil { mi.before(ctx, execCtx) } + return nil } // After -func (mi *mockSQLInterceptor) After(ctx context.Context, execCtx *exec.ExecContext) { +func (mi *mockSQLInterceptor) After(ctx context.Context, execCtx *exec.ExecContext) error { if mi.after != nil { mi.after(ctx, execCtx) } + return nil } type mockTxHook struct { diff --git a/pkg/datasource/sql/connector_test.go b/pkg/datasource/sql/connector_test.go index bcdf5f3b..ee2cce0b 100644 --- a/pkg/datasource/sql/connector_test.go +++ b/pkg/datasource/sql/connector_test.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/golang/mock/gomock" + "github.com/seata/seata-go/pkg/common/reflectx" "github.com/seata/seata-go/pkg/datasource/sql/mock" "github.com/seata/seata-go/pkg/datasource/sql/types" "github.com/stretchr/testify/assert" @@ -47,7 +48,7 @@ func initMockAtConnector(t *testing.T, ctrl *gomock.Controller, db *sql.DB, f in } field := v.FieldByName("connector") - fieldVal := GetUnexportedField(field) + fieldVal := reflectx.GetUnexportedField(field) atConnector, ok := fieldVal.(*seataATConnector) assert.True(t, ok, "need return seata at connector") @@ -56,7 +57,7 @@ func initMockAtConnector(t *testing.T, ctrl *gomock.Controller, db *sql.DB, f in if v.Kind() == reflect.Ptr { v = v.Elem() } - SetUnexportedField(v.FieldByName("target"), f(t, ctrl)) + reflectx.SetUnexportedField(v.FieldByName("target"), f(t, ctrl)) return fieldVal.(driver.Connector) } @@ -91,7 +92,7 @@ func initMockXaConnector(t *testing.T, ctrl *gomock.Controller, db *sql.DB, f in } field := v.FieldByName("connector") - fieldVal := GetUnexportedField(field) + fieldVal := reflectx.GetUnexportedField(field) atConnector, ok := fieldVal.(*seataXAConnector) assert.True(t, ok, "need return seata xa connector") @@ -100,7 +101,7 @@ func initMockXaConnector(t *testing.T, ctrl *gomock.Controller, db *sql.DB, f in if v.Kind() == reflect.Ptr { v = v.Elem() } - SetUnexportedField(v.FieldByName("target"), f(t, ctrl)) + reflectx.SetUnexportedField(v.FieldByName("target"), f(t, ctrl)) return fieldVal.(driver.Connector) } diff --git a/pkg/datasource/sql/datasource/mysql/default.go b/pkg/datasource/sql/datasource/mysql/default.go index 99a825f0..37d84f1e 100644 --- a/pkg/datasource/sql/datasource/mysql/default.go +++ b/pkg/datasource/sql/datasource/mysql/default.go @@ -22,6 +22,7 @@ import ( "github.com/seata/seata-go/pkg/datasource/sql/types" ) +// todo func init() { datasource.RegisterTableCache(types.DBTypeMySQL, func() datasource.TableMetaCache { return &tableMetaCache{} diff --git a/pkg/datasource/sql/driver.go b/pkg/datasource/sql/driver.go index 87f32515..70ce07c4 100644 --- a/pkg/datasource/sql/driver.go +++ b/pkg/datasource/sql/driver.go @@ -24,11 +24,10 @@ import ( "fmt" "reflect" "strings" - "unsafe" - - "github.com/seata/seata-go/pkg/common/log" "github.com/go-sql-driver/mysql" + "github.com/seata/seata-go/pkg/common/log" + "github.com/seata/seata-go/pkg/common/reflectx" "github.com/seata/seata-go/pkg/datasource/sql/datasource" "github.com/seata/seata-go/pkg/datasource/sql/types" "github.com/seata/seata-go/pkg/protocol/branch" @@ -116,7 +115,7 @@ func (d *seataDriver) Open(name string) (driver.Conn, error) { return nil, err } - SetUnexportedField(field, proxy) + reflectx.SetUnexportedField(field, proxy) return conn, nil } @@ -193,9 +192,9 @@ func registerResource(connector driver.Connector, txType types.TransactionType, } return &seataConnector{ - res: res, - target: connector, - conf: conf, + res: res, + target: connector, + conf: conf, }, nil } @@ -241,13 +240,3 @@ func parseResourceID(dsn string) string { return strings.ReplaceAll(res, ",", "|") } - -func GetUnexportedField(field reflect.Value) interface{} { - return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Interface() -} - -func SetUnexportedField(field reflect.Value, value interface{}) { - reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())). - Elem(). - Set(reflect.ValueOf(value)) -} diff --git a/pkg/datasource/sql/driver_test.go b/pkg/datasource/sql/driver_test.go index 13c5d512..bf4b71ce 100644 --- a/pkg/datasource/sql/driver_test.go +++ b/pkg/datasource/sql/driver_test.go @@ -23,7 +23,7 @@ import ( "testing" "github.com/golang/mock/gomock" - + "github.com/seata/seata-go/pkg/common/reflectx" "github.com/seata/seata-go/pkg/datasource/sql/datasource" "github.com/seata/seata-go/pkg/datasource/sql/mock" "github.com/seata/seata-go/pkg/protocol/branch" @@ -60,7 +60,7 @@ func Test_seataATDriver_OpenConnector(t *testing.T) { } field := v.FieldByName("connector") - fieldVal := GetUnexportedField(field) + fieldVal := reflectx.GetUnexportedField(field) _, ok := fieldVal.(*seataATConnector) assert.True(t, ok, "need return seata at connector") @@ -86,7 +86,7 @@ func Test_seataXADriver_OpenConnector(t *testing.T) { } field := v.FieldByName("connector") - fieldVal := GetUnexportedField(field) + fieldVal := reflectx.GetUnexportedField(field) _, ok := fieldVal.(*seataXAConnector) assert.True(t, ok, "need return seata xa connector") diff --git a/pkg/datasource/sql/exec/executor.go b/pkg/datasource/sql/exec/executor.go index 819724ed..fa7583c4 100644 --- a/pkg/datasource/sql/exec/executor.go +++ b/pkg/datasource/sql/exec/executor.go @@ -48,7 +48,7 @@ type ( SQLExecutor interface { // Interceptors - interceptors(interceptors []SQLInterceptor) + interceptors(interceptors []SQLHook) // Exec ExecWithNamedValue(ctx context.Context, execCtx *ExecContext, f CallbackWithNamedValue) (types.ExecResult, error) // Exec @@ -59,7 +59,7 @@ type ( // BuildExecutor func BuildExecutor(dbType types.DBType, txType types.TransactionType, query string) (SQLExecutor, error) { if txType == types.XAMode { - hooks := make([]SQLInterceptor, 0, 4) + hooks := make([]SQLHook, 0, 4) hooks = append(hooks, commonHook...) e := &BaseExecutor{} @@ -72,7 +72,7 @@ func BuildExecutor(dbType types.DBType, txType types.TransactionType, query stri return nil, err } - hooks := make([]SQLInterceptor, 0, 4) + hooks := make([]SQLHook, 0, 4) hooks = append(hooks, commonHook...) hooks = append(hooks, hookSolts[parseCtx.SQLType]...) @@ -99,12 +99,12 @@ func BuildExecutor(dbType types.DBType, txType types.TransactionType, query stri } type BaseExecutor struct { - is []SQLInterceptor + is []SQLHook ex SQLExecutor } -// interceptors -func (e *BaseExecutor) interceptors(interceptors []SQLInterceptor) { +// Interceptors +func (e *BaseExecutor) interceptors(interceptors []SQLHook) { e.is = interceptors } diff --git a/pkg/datasource/sql/exec/hook.go b/pkg/datasource/sql/exec/hook.go index fc550772..0344d0f5 100644 --- a/pkg/datasource/sql/exec/hook.go +++ b/pkg/datasource/sql/exec/hook.go @@ -25,26 +25,26 @@ import ( ) var ( - commonHook = make([]SQLInterceptor, 0, 4) + commonHook = make([]SQLHook, 0, 4) // todo support distinguish between different db type - hookSolts = map[types.SQLType][]SQLInterceptor{} + hookSolts = map[types.SQLType][]SQLHook{} ) // RegisCommonHook not goroutine safe -func RegisCommonHook(hook SQLInterceptor) { +func RegisCommonHook(hook SQLHook) { commonHook = append(commonHook, hook) } func CleanCommonHook() { - commonHook = make([]SQLInterceptor, 0, 4) + commonHook = make([]SQLHook, 0, 4) } // RegisHook not goroutine safe -func RegisHook(hook SQLInterceptor) { +func RegisHook(hook SQLHook) { _, ok := hookSolts[hook.Type()] if !ok { - hookSolts[hook.Type()] = make([]SQLInterceptor, 0, 4) + hookSolts[hook.Type()] = make([]SQLHook, 0, 4) } hookSolts[hook.Type()] = append(hookSolts[hook.Type()], hook) @@ -56,18 +56,21 @@ type ExecContext struct { Query string NamedValues []driver.NamedValue Values []driver.Value + // metaData + MetaData types.TableMeta + Conn driver.Conn } // SQLHook SQL execution front and back interceptor // case 1. Used to intercept SQL to achieve the generation of front and rear mirrors // case 2. Burning point to report // case 3. SQL black and white list -type SQLInterceptor interface { +type SQLHook interface { Type() types.SQLType // Before - Before(ctx context.Context, execCtx *ExecContext) + Before(ctx context.Context, execCtx *ExecContext) error // After - After(ctx context.Context, execCtx *ExecContext) + After(ctx context.Context, execCtx *ExecContext) error } diff --git a/pkg/datasource/sql/exec/hook/basic_undo_builder.go b/pkg/datasource/sql/hook/basic_undo_builder.go similarity index 99% rename from pkg/datasource/sql/exec/hook/basic_undo_builder.go rename to pkg/datasource/sql/hook/basic_undo_builder.go index 2ccd19a1..67857e55 100644 --- a/pkg/datasource/sql/exec/hook/basic_undo_builder.go +++ b/pkg/datasource/sql/hook/basic_undo_builder.go @@ -15,11 +15,12 @@ * limitations under the License. */ -package exec +package hook import ( "context" "fmt" + "github.com/arana-db/parser/ast" "github.com/arana-db/parser/format" "github.com/seata/seata-go/pkg/common/bytes" diff --git a/pkg/datasource/sql/exec/hook/basic_undo_builder_test.go b/pkg/datasource/sql/hook/basic_undo_builder_test.go similarity index 99% rename from pkg/datasource/sql/exec/hook/basic_undo_builder_test.go rename to pkg/datasource/sql/hook/basic_undo_builder_test.go index 1e49ddff..6ea86d8e 100644 --- a/pkg/datasource/sql/exec/hook/basic_undo_builder_test.go +++ b/pkg/datasource/sql/hook/basic_undo_builder_test.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package exec +package hook import ( "testing" diff --git a/pkg/datasource/sql/exec/hook/logger_hook.go b/pkg/datasource/sql/hook/logger_hook.go similarity index 95% rename from pkg/datasource/sql/exec/hook/logger_hook.go rename to pkg/datasource/sql/hook/logger_hook.go index 039ea9a6..8dfebb8b 100644 --- a/pkg/datasource/sql/exec/hook/logger_hook.go +++ b/pkg/datasource/sql/hook/logger_hook.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package exec +package hook import ( "context" @@ -37,7 +37,7 @@ func (h *loggerSQLHook) Type() types.SQLType { } // Before -func (h *loggerSQLHook) Before(ctx context.Context, execCtx *exec.ExecContext) { +func (h *loggerSQLHook) Before(ctx context.Context, execCtx *exec.ExecContext) error { var txID string if execCtx.TxCtx != nil { txID = execCtx.TxCtx.LocalTransID @@ -56,8 +56,10 @@ func (h *loggerSQLHook) Before(ctx context.Context, execCtx *exec.ExecContext) { } log.Debug("sql exec log", fields) + return nil } // After -func (h *loggerSQLHook) After(ctx context.Context, execCtx *exec.ExecContext) { +func (h *loggerSQLHook) After(ctx context.Context, execCtx *exec.ExecContext) error { + return nil } diff --git a/pkg/datasource/sql/hook/undo_log_hook.go b/pkg/datasource/sql/hook/undo_log_hook.go new file mode 100644 index 00000000..a67ea93a --- /dev/null +++ b/pkg/datasource/sql/hook/undo_log_hook.go @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package hook + +import ( + "context" + + "github.com/seata/seata-go/pkg/datasource/sql/exec" + + "github.com/seata/seata-go/pkg/datasource/sql/parser" + "github.com/seata/seata-go/pkg/datasource/sql/undo" + "github.com/seata/seata-go/pkg/tm" + + "github.com/seata/seata-go/pkg/datasource/sql/types" +) + +func init() { + exec.RegisCommonHook(&undoLogSQLHook{}) +} + +type undoLogSQLHook struct { +} + +func (h *undoLogSQLHook) Type() types.SQLType { + return types.SQLTypeUnknown +} + +// Before +func (h *undoLogSQLHook) Before(ctx context.Context, execCtx *exec.ExecContext) error { + if !tm.IsTransactionOpened(ctx) { + return nil + } + + pc, err := parser.DoParser(execCtx.Query) + if err != nil { + return err + } + if !pc.HasValidStmt() { + return nil + } + + builder := undo.GetUndologBuilder(pc.SQLType) + if builder == nil { + return nil + } + recordImage, err := builder.BeforeImage(ctx, execCtx) + if err != nil { + return err + } + execCtx.TxCtx.RoundImages.AppendBeofreImage(recordImage) + return nil +} + +// After +func (h *undoLogSQLHook) After(ctx context.Context, execCtx *exec.ExecContext) error { + if !tm.IsTransactionOpened(ctx) { + return nil + } + return nil +} diff --git a/pkg/datasource/sql/exec/hook/update_undo_hook.go b/pkg/datasource/sql/hook/update_undo_hook.go similarity index 99% rename from pkg/datasource/sql/exec/hook/update_undo_hook.go rename to pkg/datasource/sql/hook/update_undo_hook.go index f00a4460..508be082 100644 --- a/pkg/datasource/sql/exec/hook/update_undo_hook.go +++ b/pkg/datasource/sql/hook/update_undo_hook.go @@ -15,7 +15,7 @@ * limitations under the License. */ -package exec +package hook import ( "context" diff --git a/pkg/datasource/sql/mock/mock_datasource_manager.go b/pkg/datasource/sql/mock/mock_datasource_manager.go index 5978bd5b..cf4c42cb 100644 --- a/pkg/datasource/sql/mock/mock_datasource_manager.go +++ b/pkg/datasource/sql/mock/mock_datasource_manager.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Code generated by MockGen. DO NOT EDIT. // Source: datasource_manager.go @@ -7,13 +24,14 @@ package mock import ( context "context" sql "database/sql" + reflect "reflect" + gomock "github.com/golang/mock/gomock" datasource "github.com/seata/seata-go/pkg/datasource/sql/datasource" types "github.com/seata/seata-go/pkg/datasource/sql/types" branch "github.com/seata/seata-go/pkg/protocol/branch" message "github.com/seata/seata-go/pkg/protocol/message" rm "github.com/seata/seata-go/pkg/rm" - reflect "reflect" ) // MockDataSourceManager is a mock of DataSourceManager interface diff --git a/pkg/datasource/sql/mock/mock_driver.go b/pkg/datasource/sql/mock/mock_driver.go index 89012310..eedc9d59 100644 --- a/pkg/datasource/sql/mock/mock_driver.go +++ b/pkg/datasource/sql/mock/mock_driver.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + // Code generated by MockGen. DO NOT EDIT. // Source: test_driver.go @@ -7,8 +24,9 @@ package mock import ( context "context" driver "database/sql/driver" - gomock "github.com/golang/mock/gomock" reflect "reflect" + + gomock "github.com/golang/mock/gomock" ) // MockTestDriverConnector is a mock of TestDriverConnector interface diff --git a/pkg/datasource/sql/parser/parser_factory.go b/pkg/datasource/sql/parser/parser_factory.go index 156f36e0..9319cdf2 100644 --- a/pkg/datasource/sql/parser/parser_factory.go +++ b/pkg/datasource/sql/parser/parser_factory.go @@ -50,6 +50,10 @@ type ParseContext struct { DeleteStmt *ast.DeleteStmt } +func (p *ParseContext) HasValidStmt() bool { + return p.InsertStmt != nil || p.UpdateStmt != nil || p.DeleteStmt != nil +} + func DoParser(query string) (*ParseContext, error) { p := aparser.New() stmtNode, err := p.ParseOneStmt(query, "", "") diff --git a/pkg/datasource/sql/plugin.go b/pkg/datasource/sql/plugin.go index ad6b8b5b..eab60f44 100644 --- a/pkg/datasource/sql/plugin.go +++ b/pkg/datasource/sql/plugin.go @@ -18,7 +18,7 @@ package sql import ( - _ "github.com/seata/seata-go/pkg/datasource/sql/exec/hook" + _ "github.com/seata/seata-go/pkg/datasource/sql/hook" // mysql 相关插件 _ "github.com/seata/seata-go/pkg/datasource/sql/datasource/mysql" diff --git a/pkg/datasource/sql/types/const.go b/pkg/datasource/sql/types/const.go new file mode 100644 index 00000000..e53d7ab4 --- /dev/null +++ b/pkg/datasource/sql/types/const.go @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package types + +import ( + "database/sql" + "reflect" +) + +// https://dev.mysql.com/doc/internals/en/com-query-response.html#packet-Protocol::ColumnType +type FieldType byte + +const ( + FieldTypeDecimal FieldType = iota + FieldTypeTiny + FieldTypeShort + FieldTypeLong + FieldTypeFloat + FieldTypeDouble + FieldTypeNULL + FieldTypeTimestamp + FieldTypeLongLong + FieldTypeInt24 + FieldTypeDate + FieldTypeTime + FieldTypeDateTime + FieldTypeYear + FieldTypeNewDate + FieldTypeVarChar + FieldTypeBit +) + +const ( + FieldTypeJSON FieldType = iota + 0xf5 + FieldTypeNewDecimal + FieldTypeEnum + FieldTypeSet + FieldTypeTinyBLOB + FieldTypeMediumBLOB + FieldTypeLongBLOB + FieldTypeBLOB + FieldTypeVarString + FieldTypeString + FieldTypeGeometry +) + +type nullTime = sql.NullTime + +var ( + ScanTypeFloat32 = reflect.TypeOf(float32(0)) + ScanTypeFloat64 = reflect.TypeOf(float64(0)) + ScanTypeInt8 = reflect.TypeOf(int8(0)) + ScanTypeInt16 = reflect.TypeOf(int16(0)) + ScanTypeInt32 = reflect.TypeOf(int32(0)) + ScanTypeInt64 = reflect.TypeOf(int64(0)) + ScanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) + ScanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) + ScanTypeNullTime = reflect.TypeOf(nullTime{}) + ScanTypeUint8 = reflect.TypeOf(uint8(0)) + ScanTypeUint16 = reflect.TypeOf(uint16(0)) + ScanTypeUint32 = reflect.TypeOf(uint32(0)) + ScanTypeUint64 = reflect.TypeOf(uint64(0)) + ScanTypeRawBytes = reflect.TypeOf(sql.RawBytes{}) + ScanTypeUnknown = reflect.TypeOf(new(interface{})) +) + +// JDBCType's source is seata java: java.sql.Types.java +// it used in undo_log.rollback_info.sqlUndoLogs.afterImage.rows.fields.type field +type JDBCType int16 + +const ( + JDBCTypeBit JDBCType = -7 + JDBCTypeTinyInt JDBCType = -6 + JDBCTypeSmallInt JDBCType = 5 + JDBCTypeInteger JDBCType = 4 + JDBCTypeBigInt JDBCType = -5 + JDBCTypeFloat JDBCType = 6 + JDBCTypeReal JDBCType = 7 + JDBCTypeDouble JDBCType = 8 + JDBCTypeNumberic JDBCType = 2 + JDBCTypeDecimal JDBCType = 3 + JDBCTypeChar JDBCType = 1 + JDBCTypeVarchar JDBCType = 12 + JDBCTypeLongVarchar JDBCType = -1 + JDBCTypeDate JDBCType = 91 + JDBCTypeTime JDBCType = 92 + JDBCTypeTimestamp JDBCType = 93 + JDBCTypeBinary JDBCType = -2 + JDBCTypeVarBinary JDBCType = -3 + JDBCTypeLongVarBinary JDBCType = -4 + JDBCTypeNull JDBCType = 0 + JDBCTypeOther JDBCType = 1111 + JDBCTypeJavaObject JDBCType = 2000 + JDBCTypeDistinct JDBCType = 2001 + JDBCTypeStruct JDBCType = 2002 + JDBCTypeArray JDBCType = 2003 + JDBCTypeBlob JDBCType = 2004 + JDBCTypeClob JDBCType = 2005 + JDBCTypeRef JDBCType = 2006 + JDBCTypeDateLink JDBCType = 70 + JDBCTypeBoolean JDBCType = 16 + JDBCTypeRowID JDBCType = -8 + JDBCTypeNchar JDBCType = -15 + JDBCTypeNvarchar JDBCType = -9 + JDBCTypeLongNvVarchar JDBCType = -16 + JDBCTypeNclob JDBCType = 2011 + JDBCTypeSqlXML JDBCType = 2009 + JDBCTypeRefCursor JDBCType = 2012 + JDBCTypeTimeWithTimeZone JDBCType = 2013 + JDBCTypeTimestampWithTimezone JDBCType = 2014 +) + +// todo perfect all type name +func GetJDBCTypeByTypeName(typeName string) JDBCType { + switch typeName { + case "BIT": + return JDBCTypeBit + case "TEXT": + return JDBCTypeLongVarchar + case "BLOB": + return JDBCTypeBlob + case "DATE": + return JDBCTypeDate + case "DATETIME": + return JDBCTypeTimestamp + case "DECIMAL": + return JDBCTypeDecimal + case "DOUBLE": + return JDBCTypeDouble + case "ENUM": + return JDBCTypeTinyInt + // todo 待完善 + //case fieldTypeEnum: + // return "ENUM" + //case fieldTypeFloat: + // return "FLOAT" + //case fieldTypeGeometry: + // return "GEOMETRY" + //case fieldTypeInt24: + // return "MEDIUMINT" + //case fieldTypeJSON: + // return "JSON" + //case fieldTypeLong: + // return "INT" + //case fieldTypeLongBLOB: + // if mf.charSet != collations[binaryCollation] { + // return "LONGTEXT" + // } + // return "LONGBLOB" + //case fieldTypeLongLong: + // return "BIGINT" + //case fieldTypeMediumBLOB: + // if mf.charSet != collations[binaryCollation] { + // return "MEDIUMTEXT" + // } + // return "MEDIUMBLOB" + //case fieldTypeNewDate: + // return "DATE" + //case fieldTypeNewDecimal: + // return "DECIMAL" + //case fieldTypeNULL: + // return "NULL" + //case fieldTypeSet: + // return "SET" + //case fieldTypeShort: + // return "SMALLINT" + //case fieldTypeString: + // if mf.charSet == collations[binaryCollation] { + // return "BINARY" + // } + // return "CHAR" + //case fieldTypeTime: + // return "TIME" + //case fieldTypeTimestamp: + // return "TIMESTAMP" + //case fieldTypeTiny: + // return "TINYINT" + //case fieldTypeTinyBLOB: + // if mf.charSet != collations[binaryCollation] { + // return "TINYTEXT" + // } + // return "TINYBLOB" + //case fieldTypeVarChar: + // if mf.charSet == collations[binaryCollation] { + // return "VARBINARY" + // } + // return "VARCHAR" + //case fieldTypeVarString: + // if mf.charSet == collations[binaryCollation] { + // return "VARBINARY" + // } + // return "VARCHAR" + //case fieldTypeYear: + // return "YEAR" + default: + return -1 + } +} diff --git a/pkg/datasource/sql/types/image.go b/pkg/datasource/sql/types/image.go index 0afcbeb8..90f8813a 100644 --- a/pkg/datasource/sql/types/image.go +++ b/pkg/datasource/sql/types/image.go @@ -17,10 +17,6 @@ package types -import ( - gosql "database/sql" -) - // RoundRecordImage Front and rear mirror data type RoundRecordImage struct { bIndex int32 @@ -89,29 +85,29 @@ func (rs RecordImages) Reserve() { // RecordImage type RecordImage struct { // index - index int32 - // Table table name - Table string + index int32 `json:"-"` + // TableName table name + TableName string `json:"tableName"` // SQLType sql type - SQLType SQLType + SQLType SQLType `json:"-"` // Rows - Rows []RowImage + Rows []RowImage `json:"rows"` } // RowImage Mirror data information information type RowImage struct { // Columns All columns of image data - Columns []ColumnImage + Columns []ColumnImage `json:"fields"` } // ColumnImage The mirror data information of the column type ColumnImage struct { // KeyType index type - KeyType string + KeyType IndexType `json:"keyType"` // Name column name - Name string + Name string `json:"name"` // Type column type - Type gosql.ColumnType + Type int16 `json:"type"` // Value column value - Value interface{} + Value interface{} `json:"value"` } diff --git a/pkg/datasource/sql/types/types.go b/pkg/datasource/sql/types/types.go index ca2a9b31..5269bbba 100644 --- a/pkg/datasource/sql/types/types.go +++ b/pkg/datasource/sql/types/types.go @@ -35,6 +35,11 @@ type ( IndexType int16 ) +const ( + IndexTypeNull IndexType = 0 + IndexTypePrimaryKey IndexType = 1 +) + const ( _ DBType = iota DBTypeUnknown diff --git a/pkg/datasource/sql/undo/base/undo.go b/pkg/datasource/sql/undo/base/undo.go index 61292b62..28b90e91 100644 --- a/pkg/datasource/sql/undo/base/undo.go +++ b/pkg/datasource/sql/undo/base/undo.go @@ -21,9 +21,10 @@ import ( "context" "database/sql" "database/sql/driver" - "github.com/arana-db/parser/mysql" "strings" + "github.com/arana-db/parser/mysql" + "github.com/pkg/errors" "github.com/seata/seata-go/pkg/common/log" "github.com/seata/seata-go/pkg/common/util" diff --git a/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go b/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go new file mode 100644 index 00000000..1199ce62 --- /dev/null +++ b/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package builder + +import ( + "database/sql" + "database/sql/driver" + "io" + + "github.com/arana-db/parser/ast" + "github.com/arana-db/parser/test_driver" + gxsort "github.com/dubbogo/gost/sort" + "github.com/seata/seata-go/pkg/datasource/sql/types" +) + +type BasicUndoLogBuilder struct { +} + +// getScanSlice get the column type for scann +func (*BasicUndoLogBuilder) getScanSlice(columnNames []string, tableMeta types.TableMeta) []driver.Value { + scanSlice := make([]driver.Value, 0, len(columnNames)) + for _, columnNmae := range columnNames { + var ( + scanVal interface{} + // 从metData获取该列的元信息 + columnMeta = tableMeta.Columns[columnNmae] + ) + + switch columnMeta.Info.ScanType() { + case types.ScanTypeFloat32: + scanVal = float32(0) + break + case types.ScanTypeFloat64: + scanVal = float64(0) + break + case types.ScanTypeInt8: + scanVal = int8(0) + break + case types.ScanTypeInt16: + scanVal = int16(0) + break + case types.ScanTypeInt32: + scanVal = int32(0) + break + case types.ScanTypeInt64: + scanVal = int64(0) + break + case types.ScanTypeNullFloat: + scanVal = sql.NullFloat64{} + break + case types.ScanTypeNullInt: + scanVal = sql.NullInt64{} + break + case types.ScanTypeNullTime: + scanVal = sql.NullTime{} + break + case types.ScanTypeUint8: + scanVal = uint8(0) + break + case types.ScanTypeUint16: + scanVal = uint16(0) + break + case types.ScanTypeUint32: + scanVal = uint32(0) + break + case types.ScanTypeUint64: + scanVal = uint64(0) + break + case types.ScanTypeRawBytes: + scanVal = sql.RawBytes{} + break + case types.ScanTypeUnknown: + scanVal = new(interface{}) + break + } + scanSlice = append(scanSlice, &scanVal) + } + + return scanSlice +} + +func (b *BasicUndoLogBuilder) buildSelectArgs(stmt *ast.SelectStmt, args []driver.Value) []driver.Value { + var ( + selectArgsIndexs = make([]int32, 0) + selectArgs = make([]driver.Value, 0) + ) + b.traversalArgs(stmt.Where, &selectArgsIndexs) + if stmt.OrderBy != nil { + for _, item := range stmt.OrderBy.Items { + b.traversalArgs(item, &selectArgsIndexs) + } + } + if stmt.Limit != nil { + if stmt.Limit.Offset != nil { + b.traversalArgs(stmt.Limit.Offset, &selectArgsIndexs) + } + if stmt.Limit.Count != nil { + b.traversalArgs(stmt.Limit.Count, &selectArgsIndexs) + } + } + // sort selectArgs index array + gxsort.Int32(selectArgsIndexs) + for _, index := range selectArgsIndexs { + selectArgs = append(selectArgs, args[index]) + } + + return selectArgs +} + +// todo perfect all sql operation +func (b *BasicUndoLogBuilder) traversalArgs(node ast.Node, argsIndex *[]int32) { + if node == nil { + return + } + switch node.(type) { + case *ast.BinaryOperationExpr: + expr := node.(*ast.BinaryOperationExpr) + b.traversalArgs(expr.L, argsIndex) + b.traversalArgs(expr.R, argsIndex) + break + case *ast.BetweenExpr: + expr := node.(*ast.BetweenExpr) + b.traversalArgs(expr.Left, argsIndex) + b.traversalArgs(expr.Right, argsIndex) + break + case *ast.PatternInExpr: + exprs := node.(*ast.PatternInExpr).List + for i := 0; i < len(exprs); i++ { + b.traversalArgs(exprs[i], argsIndex) + } + break + case *test_driver.ParamMarkerExpr: + *argsIndex = append(*argsIndex, int32(node.(*test_driver.ParamMarkerExpr).Order)) + break + } +} + +func (u *BasicUndoLogBuilder) buildRecordImages(rowsi driver.Rows, tableMetaData types.TableMeta) (*types.RecordImage, error) { + // select column names + columnNames := rowsi.Columns() + rowImages := make([]types.RowImage, 0) + ss := u.getScanSlice(columnNames, tableMetaData) + + for { + err := rowsi.Next(ss) + if err == io.EOF { + break + } + + columns := make([]types.ColumnImage, 0) + // build record image + for i, name := range columnNames { + columnMeta := tableMetaData.Columns[name] + + keyType := types.IndexTypeNull + if data, ok := tableMetaData.Indexs[name]; ok { + keyType = data.IType + } + jdbcType := types.GetJDBCTypeByTypeName(columnMeta.Info.DatabaseTypeName()) + + columns = append(columns, types.ColumnImage{ + KeyType: keyType, + Name: name, + Type: int16(jdbcType), + Value: ss[i], + }) + } + rowImages = append(rowImages, types.RowImage{Columns: columns}) + } + + return &types.RecordImage{TableName: tableMetaData.Name, Rows: rowImages}, nil +} diff --git a/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder.go b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder.go new file mode 100644 index 00000000..3d7ace25 --- /dev/null +++ b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder.go @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package builder + +import ( + "context" + "database/sql/driver" + "fmt" + + "github.com/seata/seata-go/pkg/datasource/sql/exec" + + "github.com/arana-db/parser/ast" + "github.com/arana-db/parser/format" + "github.com/seata/seata-go/pkg/common/bytes" + "github.com/seata/seata-go/pkg/common/log" + "github.com/seata/seata-go/pkg/datasource/sql/parser" + "github.com/seata/seata-go/pkg/datasource/sql/types" +) + +type MySQLUpdateUndoLogBuilder struct { + BasicUndoLogBuilder +} + +func (u *MySQLUpdateUndoLogBuilder) BeforeImage(ctx context.Context, execCtx *exec.ExecContext) (*types.RecordImage, error) { + vals := execCtx.Values + if vals == nil { + for n, param := range execCtx.NamedValues { + vals[n] = param.Value + } + } + selectSQL, selectArgs, err := u.buildBeforeImageSQL(execCtx.Query, vals) + if err != nil { + return nil, err + } + + stmt, err := execCtx.Conn.Prepare(selectSQL) + if err != nil { + log.Errorf("build prepare stmt: %+v", err) + return nil, err + } + + rows, err := stmt.Query(selectArgs) + if err != nil { + log.Errorf("stmt query: %+v", err) + return nil, err + } + + return u.buildRecordImages(rows, execCtx.MetaData) +} + +func (u *MySQLUpdateUndoLogBuilder) AfterImage(types.RecordImages) (*types.RecordImages, error) { + return nil, nil +} + +// buildBeforeImageSQL build select sql from update sql +func (u *MySQLUpdateUndoLogBuilder) buildBeforeImageSQL(query string, args []driver.Value) (string, []driver.Value, error) { + p, err := parser.DoParser(query) + if err != nil { + return "", nil, err + } + + if p.UpdateStmt == nil { + log.Errorf("invalid update stmt") + return "", nil, fmt.Errorf("invalid update stmt") + } + + fields := []*ast.SelectField{} + + for _, column := range p.UpdateStmt.List { + fields = append(fields, &ast.SelectField{ + Expr: &ast.ColumnNameExpr{ + Name: column.Column, + }, + }) + } + + selStmt := ast.SelectStmt{ + SelectStmtOpts: &ast.SelectStmtOpts{}, + From: p.UpdateStmt.TableRefs, + Where: p.UpdateStmt.Where, + Fields: &ast.FieldList{Fields: fields}, + OrderBy: p.UpdateStmt.Order, + Limit: p.UpdateStmt.Limit, + TableHints: p.UpdateStmt.TableHints, + } + + b := bytes.NewByteBuffer([]byte{}) + selStmt.Restore(format.NewRestoreCtx(format.RestoreKeyWordUppercase, b)) + sql := string(b.Bytes()) + log.Infof("build select sql by update sourceQuery, sql {}", sql) + + return sql, u.buildSelectArgs(&selStmt, args), nil +} + +func (u *MySQLUpdateUndoLogBuilder) GetSQLType() types.SQLType { + return types.SQLTypeUpdate +} diff --git a/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go new file mode 100644 index 00000000..45f0490c --- /dev/null +++ b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package builder + +import ( + "database/sql/driver" + "testing" + + _ "github.com/arana-db/parser/test_driver" + _ "github.com/seata/seata-go/pkg/common/log" + "github.com/stretchr/testify/assert" +) + +func TestBuildBeforeImageSQL(t *testing.T) { + var ( + builder = MySQLUpdateUndoLogBuilder{} + ) + + tests := []struct { + name string + sourceQuery string + sourceQueryArgs []driver.Value + expectQuery string + expectQueryArgs []driver.Value + }{ + { + sourceQuery: "update t_user set name = ?, age = ? where id = ?", + sourceQueryArgs: []driver.Value{"Jack", 1, 100}, + expectQuery: "SELECT SQL_NO_CACHE name,age FROM t_user WHERE id=?", + expectQueryArgs: []driver.Value{100}, + }, + { + sourceQuery: "update t_user set name = ?, age = ? where id = ? and name = 'Jack' and age between ? and ?", + sourceQueryArgs: []driver.Value{"Jack", 1, 100, 18, 28}, + expectQuery: "SELECT SQL_NO_CACHE name,age FROM t_user WHERE id=? AND name=_UTF8MB4Jack AND age BETWEEN ? AND ?", + expectQueryArgs: []driver.Value{100, 18, 28}, + }, + { + sourceQuery: "update t_user set name = ?, age = ? where id = ? and name = 'Jack' and age in (?,?)", + sourceQueryArgs: []driver.Value{"Jack", 1, 100, 18, 28}, + expectQuery: "SELECT SQL_NO_CACHE name,age FROM t_user WHERE id=? AND name=_UTF8MB4Jack AND age IN (?,?)", + expectQueryArgs: []driver.Value{100, 18, 28}, + }, + { + sourceQuery: "update t_user set name = ?, age = ? where kk between ? and ? and id = ? and addr in(?,?) and age > ? order by name desc limit ?", + sourceQueryArgs: []driver.Value{"Jack", 1, 10, 20, 17, "Beijing", "Guangzhou", 18, 2}, + expectQuery: "SELECT SQL_NO_CACHE name,age FROM t_user WHERE kk BETWEEN ? AND ? AND id=? AND addr IN (?,?) AND age>? ORDER BY name DESC LIMIT ?", + expectQueryArgs: []driver.Value{10, 20, 17, "Beijing", "Guangzhou", 18, 2}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + query, args, err := builder.buildBeforeImageSQL(tt.sourceQuery, tt.sourceQueryArgs) + assert.Nil(t, err) + assert.Equal(t, tt.expectQuery, query) + assert.Equal(t, tt.expectQueryArgs, args) + }) + } +} diff --git a/pkg/datasource/sql/undo/mysql/default.go b/pkg/datasource/sql/undo/mysql/default.go index dab5f307..039df7c6 100644 --- a/pkg/datasource/sql/undo/mysql/default.go +++ b/pkg/datasource/sql/undo/mysql/default.go @@ -23,7 +23,7 @@ import ( ) func init() { - if err := undo.Regis(&undoLogManager{}); err != nil { + if err := undo.RegisterUndoLogManager(&undoLogManager{}); err != nil { panic(errors.WithStack(err)) } } diff --git a/pkg/datasource/sql/undo/undo.go b/pkg/datasource/sql/undo/undo.go index e23c5a93..b4a9906e 100644 --- a/pkg/datasource/sql/undo/undo.go +++ b/pkg/datasource/sql/undo/undo.go @@ -24,17 +24,24 @@ import ( "errors" "sync" + "github.com/seata/seata-go/pkg/datasource/sql/exec" "github.com/seata/seata-go/pkg/datasource/sql/types" + "github.com/seata/seata-go/pkg/datasource/sql/undo/builder" ) +func init() { + RegistrUndoLogBuilder(&builder.MySQLUpdateUndoLogBuilder{}) +} + var solts = map[types.DBType]*undoLogMgrHolder{} +var builders = map[types.SQLType]UndoLogBuilder{} type undoLogMgrHolder struct { once sync.Once mgr UndoLogManager } -func Regis(m UndoLogManager) error { +func RegisterUndoLogManager(m UndoLogManager) error { if _, exist := solts[m.DBType()]; exist { return nil } @@ -46,6 +53,16 @@ func Regis(m UndoLogManager) error { return nil } +func RegistrUndoLogBuilder(m UndoLogBuilder) { + if _, ok := builders[m.GetSQLType()]; !ok { + builders[m.GetSQLType()] = m + } +} + +func GetUndologBuilder(sqlType types.SQLType) UndoLogBuilder { + return builders[sqlType] +} + // UndoLogManager type UndoLogManager interface { Init() @@ -113,3 +130,9 @@ type UndoLogParser interface { // Decode Decode(b []byte) BranchUndoLog } + +type UndoLogBuilder interface { + BeforeImage(ctx context.Context, execCtx *exec.ExecContext) (*types.RecordImage, error) + AfterImage(types.RecordImages) (*types.RecordImages, error) + GetSQLType() types.SQLType +} diff --git a/pkg/datasource/sql/undo_test.go b/pkg/datasource/sql/undo_test.go index 06660944..00ee6150 100644 --- a/pkg/datasource/sql/undo_test.go +++ b/pkg/datasource/sql/undo_test.go @@ -78,7 +78,7 @@ func TestHasUndoLogTable(t *testing.T) { t.SkipNow() testHasUndoLogTable := func() { - db, err := sql.Open(SeataMySQLDriver, "root:12345678@tcp(127.0.0.1:3306)/seata_order?multiStatements=true") + db, err := sql.Open(SeataATMySQLDriver, "root:12345678@tcp(127.0.0.1:3306)/seata_order?multiStatements=true") assert.Nil(t, err) ctx := context.Background() diff --git a/pkg/integration/gin/gin_transaction_middleware.go b/pkg/integration/gin/gin_transaction_middleware.go index 6c35bb45..facd280a 100644 --- a/pkg/integration/gin/gin_transaction_middleware.go +++ b/pkg/integration/gin/gin_transaction_middleware.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package gin import ( diff --git a/pkg/tm/init.go b/pkg/tm/init.go index 78f29e91..302eb8ef 100644 --- a/pkg/tm/init.go +++ b/pkg/tm/init.go @@ -35,7 +35,7 @@ func InitTmClient() { // initConfig init config processor func initConfig() { - // todo implement + // todo implement } // initRemoting init rpc client diff --git a/sample/tcc/gin/client/main.go b/sample/tcc/gin/client/main.go index 8ab6b946..f6edaa65 100644 --- a/sample/tcc/gin/client/main.go +++ b/sample/tcc/gin/client/main.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package main import ( diff --git a/sample/tcc/gin/server/main.go b/sample/tcc/gin/server/main.go index 96177320..d112f008 100644 --- a/sample/tcc/gin/server/main.go +++ b/sample/tcc/gin/server/main.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package main import ( diff --git a/sample/tcc/gin/server/service.go b/sample/tcc/gin/server/service.go index fb83b7e9..becd4db4 100644 --- a/sample/tcc/gin/server/service.go +++ b/sample/tcc/gin/server/service.go @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package main import (