From 01ddce45b2c133dbbbbcf2c89fa1de340f75e34f Mon Sep 17 00:00:00 2001
From: a <a@a.a>
Date: Sat, 3 Sep 2022 05:36:16 -0500
Subject: [PATCH] ok i guess

---
 cmd/cgat/main.go                              |   5 +-
 codegen/protocol/packets.tmpl                 |  14 +-
 .../config_data.toml => config_data.toml      |   0
 go.mod                                        |  23 ++
 go.sum                                        | 347 +++++++++++++++++-
 lib/config/config.go                          |   6 +-
 lib/gat/client.go                             | 117 +++++-
 lib/gat/gatling.go                            |  26 +-
 lib/gat/messages.go                           |   4 +-
 lib/gat/protocol/backend.go                   | 104 +++---
 lib/gat/protocol/frontend.go                  | 112 ++++--
 lib/gat/protocol/shared.go                    |   8 +-
 lib/gat/query_router.go                       | 128 +++----
 lib/gat/query_router_test.go                  |  89 +++--
 spec/protocol/backend.yaml                    |   2 +-
 spec/protocol/frontend.yaml                   |   9 +-
 16 files changed, 755 insertions(+), 239 deletions(-)
 rename lib/config/config_data.toml => config_data.toml (100%)

diff --git a/cmd/cgat/main.go b/cmd/cgat/main.go
index 4ff4c958..aaa05000 100644
--- a/cmd/cgat/main.go
+++ b/cmd/cgat/main.go
@@ -2,12 +2,14 @@ package main
 
 import (
 	"context"
+	"log"
+
 	"gfx.cafe/gfx/pggat/lib/config"
 	"gfx.cafe/gfx/pggat/lib/gat"
 )
 
 // test config, should be changed
-const CONFIG = "./lib/config/config_data.toml"
+const CONFIG = "./config_data.toml"
 
 func main() {
 	conf, err := config.Load(CONFIG)
@@ -20,6 +22,7 @@ func main() {
 		panic(err)
 	}
 
+	log.Println("listening on port", conf.General.Port)
 	err = gatling.ListenAndServe(context.Background())
 	if err != nil {
 		panic(err)
diff --git a/codegen/protocol/packets.tmpl b/codegen/protocol/packets.tmpl
index 33493420..5474639f 100644
--- a/codegen/protocol/packets.tmpl
+++ b/codegen/protocol/packets.tmpl
@@ -85,10 +85,10 @@ var _ io.Reader
     {{else if $field.While -}}
         var P {{template "fieldTypeNoArr" (list $parent $field)}}
         for ok := true; ok; ok = {{$field.While}} {
-            {{template "readFieldL1" (list $parent $field "P")}}
-            T.{{$field.Name}} = append(T.{{$field.Name}}, P)
-            var newp {{template "fieldTypeNoArr" (list $parent $field)}}
-            P = newp
+            var newP {{template "fieldTypeNoArr" (list $parent $field)}}
+            {{template "readFieldL1" (list $parent $field "newP")}}
+            T.{{$field.Name}} = append(T.{{$field.Name}}, newP)
+            P = newP
         }
     {{else -}}
         {{template "readFieldL1" (list $parent $field (printf "T.%s" $field.Name))}}
@@ -216,9 +216,9 @@ var _ io.Reader
                 return
             }
         {{end -}}
-        _, err = WriteInt32(writer, int32(length))
+        _, err = WriteInt32(writer, int32(length) + 4)
         if err != nil {
-            length = 5
+            length += 5
             return
         }
         length += 5
@@ -228,4 +228,4 @@ var _ io.Reader
 
     var _ Packet = (*{{$name}})(nil)
 
-{{end -}}
\ No newline at end of file
+{{end -}}
diff --git a/lib/config/config_data.toml b/config_data.toml
similarity index 100%
rename from lib/config/config_data.toml
rename to config_data.toml
diff --git a/go.mod b/go.mod
index 556ba68b..979aff3f 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.19
 require (
 	git.tuxpa.in/a/zlog v1.32.0
 	github.com/BurntSushi/toml v1.2.0
+	github.com/auxten/postgresql-parser v1.0.1
 	github.com/ethereum/go-ethereum v1.10.23
 	github.com/iancoleman/strcase v0.2.0
 	github.com/xdg-go/scram v1.1.1
@@ -13,10 +14,32 @@ require (
 )
 
 require (
+	github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect
+	github.com/cockroachdb/apd v1.1.1-0.20181017181144-bced77f817b4 // indirect
+	github.com/cockroachdb/errors v1.8.2 // indirect
+	github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect
+	github.com/cockroachdb/redact v1.0.8 // indirect
+	github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect
+	github.com/dustin/go-humanize v1.0.0 // indirect
+	github.com/getsentry/raven-go v0.2.0 // indirect
+	github.com/gogo/protobuf v1.3.2 // indirect
+	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
+	github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
+	github.com/kr/pretty v0.2.0 // indirect
+	github.com/kr/text v0.2.0 // indirect
+	github.com/lib/pq v1.9.0 // indirect
 	github.com/mattn/go-colorable v0.1.12 // indirect
 	github.com/mattn/go-isatty v0.0.14 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/sirupsen/logrus v1.6.0 // indirect
+	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 	github.com/xdg-go/stringprep v1.0.3 // indirect
+	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 	golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
 	golang.org/x/text v0.3.7 // indirect
+	google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f // indirect
+	google.golang.org/grpc v1.33.1 // indirect
+	google.golang.org/protobuf v1.26.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 87098b1d..0838b82a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,36 +1,381 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY=
 git.tuxpa.in/a/zlog v1.32.0/go.mod h1:vUa2Qhu6DLPLqmfRy99FiPqaY2eb6/KQjtMekW3UNnA=
+github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
 github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw=
+github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w=
+github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
+github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM=
+github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
+github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
+github.com/auxten/postgresql-parser v1.0.1 h1:x+qiEHAe2cH55Kly64dWh4tGvUKEQwMmJgma7a1kbj4=
+github.com/auxten/postgresql-parser v1.0.1/go.mod h1:Nf27dtv8EU1C+xNkoLD3zEwfgJfDDVi8Zl86gznxPvI=
+github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
+github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cockroachdb/apd v1.1.1-0.20181017181144-bced77f817b4 h1:XWEdfNxDkZI3DXXlpo0hZJ1xdaH/f3CKuZpk93pS/Y0=
+github.com/cockroachdb/apd v1.1.1-0.20181017181144-bced77f817b4/go.mod h1:mdGz2CnkJrefFtlLevmE7JpL2zB9tKofya/6w7wWzNA=
+github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4=
+github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM=
+github.com/cockroachdb/errors v1.8.2 h1:rnnWK9Nn5kEMOGz9531HuDx/FOleL4NVH20VsDexVC8=
+github.com/cockroachdb/errors v1.8.2/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac=
+github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f h1:o/kfcElHqOiXqcou5a3rIlMc7oJbMQkeLk0VQJ7zgqY=
+github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
+github.com/cockroachdb/redact v1.0.8 h1:8QG/764wK+vmEYoOlfobpe12EQcS81ukx/a4hdVMxNw=
+github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg=
+github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 h1:IKgmqgMQlVJIZj19CdocBeSfSaiCbEBZGKODaixqtHM=
+github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ=
+github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
+github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
 github.com/ethereum/go-ethereum v1.10.23 h1:Xk8XAT4/UuqcjMLIMF+7imjkg32kfVFKoeyQDaO2yWM=
 github.com/ethereum/go-ethereum v1.10.23/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
+github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
+github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
+github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
+github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
+github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
+github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
+github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
+github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
+github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
+github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
+github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
+github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
 github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
 github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
+github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
+github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
+github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI=
+github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
+github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
+github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
+github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
+github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
+github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk=
+github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U=
+github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw=
+github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0=
+github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
+github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
+github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
+github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
+github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
+github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
 github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
 github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
+github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg=
+github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ=
+github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
+github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
+github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
+github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
+github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
+github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
+github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
+github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
+github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
+github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
+github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
+github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+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.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
+github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
+github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
+github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
 github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E=
 github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
 github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs=
 github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
+github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
+github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
+github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
+github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
+github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
+github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
+github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
 golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg=
 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f h1:Yv4xsIx7HZOoyUGSJ2ksDyWE2qIBXROsZKt2ny3hCGM=
+google.golang.org/genproto v0.0.0-20200911024640-645f7a48b24f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
+gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
+gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/lib/config/config.go b/lib/config/config.go
index 8bbaa2b1..778ada2e 100644
--- a/lib/config/config.go
+++ b/lib/config/config.go
@@ -1,8 +1,9 @@
 package config
 
 import (
-	"github.com/BurntSushi/toml"
 	"os"
+
+	"github.com/BurntSushi/toml"
 )
 
 type PoolMode string
@@ -45,6 +46,9 @@ type General struct {
 
 	BanTime int `toml:"ban_time" yaml:"ban_time" json:"ban_time"`
 
+	TlsCertificate string `toml:"tls_certificate" yaml:"tls_certificate" json:"tls_certificate"`
+	TlsPrivateKey  string `toml:"tls_private_key" yaml:"tls_private_key" json:"tls_private_key"`
+
 	AutoReload bool `toml:"autoreload" yaml:"autoreload" json:"autoreload"`
 }
 
diff --git a/lib/gat/client.go b/lib/gat/client.go
index 19f59f39..efd72bc2 100644
--- a/lib/gat/client.go
+++ b/lib/gat/client.go
@@ -5,13 +5,16 @@ import (
 	"bytes"
 	"context"
 	"crypto/rand"
+	"crypto/tls"
 	"errors"
 	"fmt"
-	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 	"io"
 	"math/big"
 	"net"
 	"reflect"
+	"strings"
+
+	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 
 	"gfx.cafe/gfx/pggat/lib/config"
 	"git.tuxpa.in/a/zlog"
@@ -101,12 +104,52 @@ func NewClient(
 }
 
 func (c *Client) Accept(ctx context.Context) error {
+	// read a packet
 	startup := new(protocol.StartupMessage)
 	err := startup.Read(c.r)
 	if err != nil {
 		return err
 	}
-
+	switch startup.Fields.ProtocolVersionNumber {
+	case 196608:
+	case 80877102:
+		return c.handle_cancel(ctx, startup)
+	case 80877103:
+		// ssl stuff now
+		useSsl := (c.conf.General.TlsCertificate != "")
+		if !useSsl {
+			_, err = protocol.WriteByte(c.wr, 'N')
+			if err != nil {
+				return err
+			}
+			startup = new(protocol.StartupMessage)
+			err := startup.Read(c.r)
+			if err != nil {
+				return err
+			}
+		} else {
+			_, err = protocol.WriteByte(c.wr, 'S')
+			if err != nil {
+				return err
+			}
+			//TODO: we need to do an ssl handshake here.
+			cert, err := tls.LoadX509KeyPair(c.conf.General.TlsCertificate, c.conf.General.TlsPrivateKey)
+			if err != nil {
+				return err
+			}
+			cfg := &tls.Config{
+				Certificates:       []tls.Certificate{cert},
+				InsecureSkipVerify: true,
+			}
+			c.conn = tls.Server(c.conn, cfg)
+			c.r = bufio.NewReader(c.conn)
+			c.wr = c.conn
+			err = startup.Read(c.r)
+			if err != nil {
+				return err
+			}
+		}
+	}
 	params := make(map[string]string)
 	for _, v := range startup.Fields.Parameters {
 		params[v.Name] = v.Value
@@ -155,7 +198,9 @@ func (c *Client) Accept(ctx context.Context) error {
 
 	var rsp protocol.Packet
 	rsp, err = protocol.ReadFrontend(c.r)
-
+	if err != nil {
+		return err
+	}
 	var passwordResponse []byte
 	switch r := rsp.(type) {
 	case *protocol.AuthenticationResponse:
@@ -165,19 +210,24 @@ func (c *Client) Accept(ctx context.Context) error {
 	}
 
 	// Authenticate admin user.
-
 	if c.admin {
 		c.server_info = AdminServerInfo()
 		pw_hash := Md5HashPassword(c.conf.General.AdminUsername, c.conf.General.AdminPassword, salt[:])
 		if !reflect.DeepEqual(pw_hash, passwordResponse) {
-			return fmt.Errorf("password denied")
+			return fmt.Errorf("password denied for admin")
 		}
 	} else {
 		// TODO: actually get a server pool
-		pool := ServerPool{}
+		c.server_info = AdminServerInfo()
+		pool := ServerPool{
+			user: config.User{
+				Name:     "postgres",
+				Password: "postgres",
+			},
+		}
 		pw_hash := Md5HashPassword(c.username, pool.user.Password, salt[:])
 		if !reflect.DeepEqual(pw_hash, passwordResponse) {
-			return fmt.Errorf("password denied")
+			return fmt.Errorf("password denied for %s", c.username)
 		}
 	}
 	c.log.Debug().Msg("Password authentication successful")
@@ -187,6 +237,8 @@ func (c *Client) Accept(ctx context.Context) error {
 	if err != nil {
 		return err
 	}
+
+	//
 	_, err = c.wr.Write(c.server_info)
 	if err != nil {
 		return err
@@ -205,6 +257,57 @@ func (c *Client) Accept(ctx context.Context) error {
 		return err
 	}
 	c.log.Debug().Msg("Ready for Query")
+	for {
+		err := c.tick(ctx)
+		if err != nil {
+			return err
+		}
+	}
+}
+
+// TODO: we need to keep track of queries so we can handle cancels
+func (c *Client) handle_cancel(ctx context.Context, p *protocol.StartupMessage) error {
+	log.Println("cancel msg", p)
+	return nil
+}
+
+// reads a packet from stream and handles it
+func (c *Client) tick(ctx context.Context) error {
+	rsp, err := protocol.ReadFrontend(c.r)
+	if err != nil {
+		return err
+	}
+	log.Println("(%v): %s", reflect.TypeOf(c), c)
+	switch cast := rsp.(type) {
+	case *protocol.Describe:
+	case *protocol.Query:
+		return c.handle_query(ctx, cast)
+	default:
+	}
+	return nil
+}
+
+func (c *Client) handle_query(ctx context.Context, q *protocol.Query) error {
+	//TODO: use the query router here
+	// get the first word of the query
+	ans := &protocol.CommandComplete{}
+	words := strings.Split(strings.ToLower(strings.TrimSpace(q.Fields.Query)), " ")
+	switch words[0] {
+	case "set":
+		ans.Fields.Data = "SET"
+	case "select":
+		ans.Fields.Data = "SELECT"
+	}
+	_, err := ans.Write(c.wr)
+	if err != nil {
+		return err
+	}
+	ready := &protocol.ReadyForQuery{}
+	ready.Fields.Status = 'I'
+	_, err = ready.Write(c.wr)
+	if err != nil {
+		return err
+	}
 	return nil
 }
 
diff --git a/lib/gat/gatling.go b/lib/gat/gatling.go
index a2176686..00f37dae 100644
--- a/lib/gat/gatling.go
+++ b/lib/gat/gatling.go
@@ -3,9 +3,11 @@ package gat
 import (
 	"context"
 	"fmt"
+	"log"
 	"net"
 
 	"gfx.cafe/gfx/pggat/lib/config"
+	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 )
 
 type Gatling struct {
@@ -42,12 +44,32 @@ func (g *Gatling) ListenAndServe(ctx context.Context) error {
 		if err != nil {
 			return err
 		}
-		go g.handleConnection(ctx, c)
+		go func() {
+			err := g.handleConnection(ctx, c)
+			if err != nil {
+				log.Println("disconnected:", err)
+			}
+		}()
 	}
 }
 
 // TODO: TLS
 func (g *Gatling) handleConnection(ctx context.Context, c net.Conn) error {
 	cl := NewClient(g.c, c, g.csm, false)
-	return cl.Accept(ctx)
+	err := cl.Accept(ctx)
+	if err != nil {
+		resp := &protocol.ErrorResponse{
+			Fields: protocol.FieldsErrorResponse{
+				Responses: []protocol.FieldsErrorResponseResponses{
+					{
+						Code:  0,
+						Value: err.Error(),
+					},
+				},
+			},
+		}
+		log.Println(err.Error())
+		resp.Write(cl.wr)
+	}
+	return nil
 }
diff --git a/lib/gat/messages.go b/lib/gat/messages.go
index 9324764f..37d6a093 100644
--- a/lib/gat/messages.go
+++ b/lib/gat/messages.go
@@ -5,6 +5,7 @@ import (
 	"crypto/md5"
 	"crypto/rand"
 	"encoding/hex"
+
 	"gfx.cafe/gfx/pggat/lib/gat/protocol"
 )
 
@@ -33,7 +34,8 @@ func Md5HashPassword(user string, password string, salt []byte) []byte {
 		[]byte(hex.EncodeToString(hsh1.Sum(nil))),
 	)
 	hsh2.Write(salt)
-	return append([]byte("md5"), hsh2.Sum(nil)...)
+	sum := hsh2.Sum(nil)
+	return append([]byte("md5"+hex.EncodeToString(sum)), 0)
 }
 
 // /// Implements a response to our custom `SET SHARDING KEY`
diff --git a/lib/gat/protocol/backend.go b/lib/gat/protocol/backend.go
index 890b969e..6159e499 100644
--- a/lib/gat/protocol/backend.go
+++ b/lib/gat/protocol/backend.go
@@ -67,9 +67,9 @@ func (T *Authentication) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -140,9 +140,9 @@ func (T *BackendKeyData) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -193,9 +193,9 @@ func (T *BindComplete) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -246,9 +246,9 @@ func (T *CloseComplete) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -309,9 +309,9 @@ func (T *CommandComplete) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -400,9 +400,9 @@ func (T *CopyBothResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -491,9 +491,9 @@ func (T *CopyInResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -582,9 +582,9 @@ func (T *CopyOutResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -704,9 +704,9 @@ func (T *DataRow) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -757,9 +757,9 @@ func (T *EmptyQueryResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -813,13 +813,13 @@ type FieldsErrorResponse struct {
 func (T *FieldsErrorResponse) Read(payloadLength int, reader io.Reader) (err error) {
 	var P FieldsErrorResponseResponses
 	for ok := true; ok; ok = P.Code != 0 {
-		err = P.Read(payloadLength, reader)
+		var newP FieldsErrorResponseResponses
+		err = newP.Read(payloadLength, reader)
 		if err != nil {
 			return
 		}
-		T.Responses = append(T.Responses, P)
-		var newp FieldsErrorResponseResponses
-		P = newp
+		T.Responses = append(T.Responses, newP)
+		P = newP
 	}
 	return
 }
@@ -865,9 +865,9 @@ func (T *ErrorResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -946,9 +946,9 @@ func (T *FunctionCallResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1037,9 +1037,9 @@ func (T *NegotiateProtocolVersion) Write(writer io.Writer) (length int, err erro
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1090,9 +1090,9 @@ func (T *NoData) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1146,13 +1146,13 @@ type FieldsNoticeResponse struct {
 func (T *FieldsNoticeResponse) Read(payloadLength int, reader io.Reader) (err error) {
 	var P FieldsNoticeResponseResponses
 	for ok := true; ok; ok = P.Code != 0 {
-		err = P.Read(payloadLength, reader)
+		var newP FieldsNoticeResponseResponses
+		err = newP.Read(payloadLength, reader)
 		if err != nil {
 			return
 		}
-		T.Responses = append(T.Responses, P)
-		var newp FieldsNoticeResponseResponses
-		P = newp
+		T.Responses = append(T.Responses, newP)
+		P = newP
 	}
 	return
 }
@@ -1198,9 +1198,9 @@ func (T *NoticeResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1281,9 +1281,9 @@ func (T *NotificationResponse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1362,9 +1362,9 @@ func (T *ParameterDescription) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1435,9 +1435,9 @@ func (T *ParameterStatus) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1488,9 +1488,9 @@ func (T *ParseComplete) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1541,9 +1541,9 @@ func (T *PortalSuspended) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1604,9 +1604,9 @@ func (T *ReadyForQuery) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1768,9 +1768,9 @@ func (T *RowDescription) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
diff --git a/lib/gat/protocol/frontend.go b/lib/gat/protocol/frontend.go
index 45cea868..b5344bdc 100644
--- a/lib/gat/protocol/frontend.go
+++ b/lib/gat/protocol/frontend.go
@@ -67,9 +67,9 @@ func (T *AuthenticationResponse) Write(writer io.Writer) (length int, err error)
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -265,9 +265,9 @@ func (T *Bind) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -342,9 +342,9 @@ func (T *CancelRequest) Write(writer io.Writer) (length int, err error) {
 		length = 0
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -415,9 +415,9 @@ func (T *Close) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -478,9 +478,9 @@ func (T *CopyFail) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -551,9 +551,9 @@ func (T *Describe) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -624,9 +624,9 @@ func (T *Execute) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -677,9 +677,9 @@ func (T *Flush) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -847,9 +847,9 @@ func (T *FunctionCall) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -904,9 +904,9 @@ func (T *GSSENCRequest) Write(writer io.Writer) (length int, err error) {
 		length = 0
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1005,9 +1005,9 @@ func (T *Parse) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1068,9 +1068,9 @@ func (T *Query) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1125,9 +1125,9 @@ func (T *SSLRequest) Write(writer io.Writer) (length int, err error) {
 		length = 0
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1176,6 +1176,8 @@ func (T *FieldsStartupMessageParameters) Write(writer io.Writer) (length int, er
 
 type FieldsStartupMessage struct {
 	ProtocolVersionNumber int32
+	ProcessKey            int32
+	SecretKey             int32
 	Parameters            []FieldsStartupMessageParameters
 }
 
@@ -1184,15 +1186,29 @@ func (T *FieldsStartupMessage) Read(payloadLength int, reader io.Reader) (err er
 	if err != nil {
 		return
 	}
-	var P FieldsStartupMessageParameters
-	for ok := true; ok; ok = P.Name != "" {
-		err = P.Read(payloadLength, reader)
+	if T.ProtocolVersionNumber == 80877102 {
+		T.ProcessKey, err = ReadInt32(reader)
 		if err != nil {
 			return
 		}
-		T.Parameters = append(T.Parameters, P)
-		var newp FieldsStartupMessageParameters
-		P = newp
+	}
+	if T.ProtocolVersionNumber == 80877102 {
+		T.SecretKey, err = ReadInt32(reader)
+		if err != nil {
+			return
+		}
+	}
+	if T.ProtocolVersionNumber == 196608 {
+		var P FieldsStartupMessageParameters
+		for ok := true; ok; ok = P.Name != "" {
+			var newP FieldsStartupMessageParameters
+			err = newP.Read(payloadLength, reader)
+			if err != nil {
+				return
+			}
+			T.Parameters = append(T.Parameters, newP)
+			P = newP
+		}
 	}
 	return
 }
@@ -1204,13 +1220,29 @@ func (T *FieldsStartupMessage) Write(writer io.Writer) (length int, err error) {
 		return
 	}
 	length += temp
-	for _, v := range T.Parameters {
-		temp, err = v.Write(writer)
+	if T.ProtocolVersionNumber == 80877102 {
+		temp, err = WriteInt32(writer, T.ProcessKey)
 		if err != nil {
 			return
 		}
 		length += temp
 	}
+	if T.ProtocolVersionNumber == 80877102 {
+		temp, err = WriteInt32(writer, T.SecretKey)
+		if err != nil {
+			return
+		}
+		length += temp
+	}
+	if T.ProtocolVersionNumber == 196608 {
+		for _, v := range T.Parameters {
+			temp, err = v.Write(writer)
+			if err != nil {
+				return
+			}
+			length += temp
+		}
+	}
 	_ = temp
 	return
 }
@@ -1237,9 +1269,9 @@ func (T *StartupMessage) Write(writer io.Writer) (length int, err error) {
 		length = 0
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1290,9 +1322,9 @@ func (T *Sync) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -1343,9 +1375,9 @@ func (T *Terminate) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
diff --git a/lib/gat/protocol/shared.go b/lib/gat/protocol/shared.go
index 30aa5c1c..567fe6b5 100644
--- a/lib/gat/protocol/shared.go
+++ b/lib/gat/protocol/shared.go
@@ -67,9 +67,9 @@ func (T *CopyData) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
@@ -120,9 +120,9 @@ func (T *CopyDone) Write(writer io.Writer) (length int, err error) {
 		length = 1
 		return
 	}
-	_, err = WriteInt32(writer, int32(length))
+	_, err = WriteInt32(writer, int32(length)+4)
 	if err != nil {
-		length = 5
+		length += 5
 		return
 	}
 	length += 5
diff --git a/lib/gat/query_router.go b/lib/gat/query_router.go
index 9aaa5b3b..7e1a6c4b 100644
--- a/lib/gat/query_router.go
+++ b/lib/gat/query_router.go
@@ -1,10 +1,17 @@
 package gat
 
 import (
+	"fmt"
 	"log"
 	"regexp"
+	"strings"
 
 	"gfx.cafe/gfx/pggat/lib/config"
+	"gfx.cafe/gfx/pggat/lib/gat/protocol"
+
+	"github.com/auxten/postgresql-parser/pkg/sql/parser"
+	"github.com/auxten/postgresql-parser/pkg/sql/sem/tree"
+	"github.com/auxten/postgresql-parser/pkg/walk"
 )
 
 var compiler = regexp.MustCompile
@@ -54,17 +61,13 @@ func (r *QueryRouter) UpdatePoolSettings(pool_settings PoolSettings) {
 }
 
 // / Try to parse a command and execute it.
-func (r *QueryRouter) try_execute_command(buf []byte) (Command, string) {
+func (r *QueryRouter) try_execute_command(pkt protocol.Query) (Command, string) {
 	// Only simple protocol supported for commands.
-	if buf[0] != 'Q' {
-		return nil, ""
-	}
-	msglen := 0
 	// TODO: read msg len
 	// msglen := buf.get_i32()
 	custom := false
 	for _, v := range CustomSqlRegex {
-		if v.Match(buf[:msglen-5]) {
+		if v.MatchString(pkt.Fields.Query) {
 			custom = true
 			break
 		}
@@ -72,7 +75,7 @@ func (r *QueryRouter) try_execute_command(buf []byte) (Command, string) {
 	// This is not a custom query, try to infer which
 	// server it'll go to if the query parser is enabled.
 	if !custom {
-		log.Println("Regular query, not a command")
+		log.Println("regular query, not a command")
 		return nil, ""
 	}
 
@@ -198,80 +201,43 @@ func (r *QueryRouter) try_execute_command(buf []byte) (Command, string) {
 
 // / Try to infer which server to connect to based on the contents of the query.
 // TODO: implement
-func (r *QueryRouter) InferRole(buf []byte) bool {
-	log.Println("Inferring role")
-
-	//code := buf.get_u8() as char
-	//len := buf.get_i32() as usize
-
-	//query := switch code {
-	//	// Query
-	//	'Q' => {
-	//		query := string(&buf[:len - 5]).to_string()
-	//		log.Println("Query: '%v'", query)
-	//		query
-	//	}
-
-	//	// Parse (prepared statement)
-	//	'P' => {
-	//		mut start := 0
-	//		mut end
-
-	//		// Skip the name of the prepared statement.
-	//		while buf[start] != 0 && start < buf.len() {
-	//			start += 1
-	//		}
-	//		start += 1 // Skip terminating null
-
-	//		// Find the end of the prepared stmt (\0)
-	//		end := start
-	//		while buf[end] != 0 && end < buf.len() {
-	//			end += 1
-	//		}
-
-	//		query := string(&buf[start:end]).to_string()
-
-	//		log.Println("Prepared statement: '%v'", query)
-
-	//		query.replace("$", "") // Remove placeholders turning them into "values"
-	//	}
-
-	//	_ => return false,
-	//}
-
-	//ast := switch Parser::parse_sql(&PostgreSqlDialect %v, &query) {
-	//	Ok(ast) => ast,
-	//	Err(err) => {
-	//		log.Println("%v", err.to_string())
-	//		return false
-	//	}
-	//}
-
-	//if ast.len() == 0 {
-	//	return false
-	//}
-
-	//switch ast[0] {
-	//	// All transactions go to the primary, probably a write.
-	//	StartTransaction { : } => {
-	//		self.active_role := Some(Role::Primary)
-	//	}
-
-	//	// Likely a read-only query
-	//	Query { : } => {
-	//		self.active_role := switch self.primary_reads_enabled {
-	//			false => Some(Role::Replica), // If primary should not be receiving reads, use a replica.
-	//			true => None,                 // Any server role is fine in this case.
-	//		}
-	//	}
-
-	//	// Likely a write
-	//	_ => {
-	//		self.active_role := Some(Role::Primary)
-	//	}
-	//}
-
-	return true
+func (r *QueryRouter) InferRole(pkt protocol.Packet) error {
+	var query string
+	switch c := pkt.(type) {
+	case *protocol.Query:
+		r.active_role = config.SERVERROLE_REPLICA
+	case *protocol.Parse:
+		query = c.Fields.Query
+		query = strings.ReplaceAll(query, "$", "")
+	default:
+		return fmt.Errorf("unknown packet %v", pkt)
+	}
+	// ok now parse the query
+	wk := &walk.AstWalker{
+		Fn: func(ctx, node any) (stop bool) {
+			switch n := node.(type) {
+			case *tree.Update, *tree.UpdateExpr,
+				*tree.BeginTransaction, *tree.CommitTransaction, *tree.RollbackTransaction,
+				*tree.SetTransaction, *tree.ShowTransactionStatus, *tree.Delete, *tree.Insert:
+				//
+				r.active_role = config.SERVERROLE_PRIMARY
+				return true
+			default:
+				_ = n
+			}
+			return false
+		},
+	}
+	r.active_role = config.SERVERROLE_REPLICA
+	stmts, err := parser.Parse(query)
+	if err != nil {
+		return err
+	}
+	_, err = wk.Walk(stmts, nil)
+	if err != nil {
+		return err
+	}
+	return nil
 }
 
 // / Get the current desired server role we should be talking to.
diff --git a/lib/gat/query_router_test.go b/lib/gat/query_router_test.go
index 9f9c0b18..a84edaa8 100644
--- a/lib/gat/query_router_test.go
+++ b/lib/gat/query_router_test.go
@@ -1,45 +1,54 @@
 package gat
 
-//TODO: adapt tests
-//#[cfg(test)]
-//mod test {
-//    use super::*;
-//    use crate::messages::simple_query;
-//    use crate::pool::PoolMode;
-//    use crate::sharding::ShardingFunction;
-//    use bytes::BufMut;
-//
-//    #[test]
-//    fn test_defaults() {
-//        QueryRouter::setup();
-//        let qr = QueryRouter::new();
-//
-//        assert_eq!(qr.role(), None);
-//    }
-//
-//    #[test]
-//    fn test_infer_role_replica() {
-//        QueryRouter::setup();
-//        let mut qr = QueryRouter::new();
-//        assert!(qr.try_execute_command(simple_query("SET SERVER ROLE TO 'auto'")) != None);
-//        assert_eq!(qr.query_parser_enabled(), true);
-//
-//        assert!(qr.try_execute_command(simple_query("SET PRIMARY READS TO off")) != None);
-//
-//        let queries = vec![
-//            simple_query("SELECT * FROM items WHERE id = 5"),
-//            simple_query(
-//                "SELECT id, name, value FROM items INNER JOIN prices ON item.id = prices.item_id",
-//            ),
-//            simple_query("WITH t AS (SELECT * FROM items) SELECT * FROM t"),
-//        ];
-//
-//        for query in queries {
-//            // It's a recognized query
-//            assert!(qr.infer_role(query));
-//            assert_eq!(qr.role(), Some(Role::Replica));
-//        }
-//    }
+import (
+	"testing"
+
+	"gfx.cafe/gfx/pggat/lib/config"
+	"gfx.cafe/gfx/pggat/lib/gat/protocol"
+)
+
+// TODO: adapt tests
+func TestQueryRouterInterRoleReplica(t *testing.T) {
+	qr := &QueryRouter{}
+	pkt := &protocol.Parse{}
+	pkt.Fields.Query = `UPDATE items SET name = 'pumpkin' WHERE id = 5`
+	err := qr.InferRole(pkt)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if qr.active_role != config.SERVERROLE_PRIMARY {
+		t.Error("expect primary")
+	}
+	pkt.Fields.Query = `select * from items WHERE id = 5`
+	err = qr.InferRole(pkt)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if qr.active_role != config.SERVERROLE_REPLICA {
+		t.Error("expect replica")
+	}
+
+}
+
+//      assert!(qr.try_execute_command(simple_query("SET SERVER ROLE TO 'auto'")) != None);
+//      assert_eq!(qr.query_parser_enabled(), true);
+
+//      assert!(qr.try_execute_command(simple_query("SET PRIMARY READS TO off")) != None);
+
+//      let queries = vec![
+//          simple_query("SELECT * FROM items WHERE id = 5"),
+//          simple_query(
+//              "SELECT id, name, value FROM items INNER JOIN prices ON item.id = prices.item_id",
+//          ),
+//          simple_query("WITH t AS (SELECT * FROM items) SELECT * FROM t"),
+//      ];
+
+//      for query in queries {
+//          // It's a recognized query
+//          assert!(qr.infer_role(query));
+//          assert_eq!(qr.role(), Some(Role::Replica));
+//      }
+//  }
 //
 //    #[test]
 //    fn test_infer_role_primary() {
diff --git a/spec/protocol/backend.yaml b/spec/protocol/backend.yaml
index eeffccbd..a314557e 100644
--- a/spec/protocol/backend.yaml
+++ b/spec/protocol/backend.yaml
@@ -147,4 +147,4 @@ RowDescription:
             Type: int32
           - Name: FormatCode
             Type: int16
-      LengthPrefixed: int16
\ No newline at end of file
+      LengthPrefixed: int16
diff --git a/spec/protocol/frontend.yaml b/spec/protocol/frontend.yaml
index 6ca2d85f..0a700e48 100644
--- a/spec/protocol/frontend.yaml
+++ b/spec/protocol/frontend.yaml
@@ -104,7 +104,14 @@ StartupMessage:
   Fields:
     - Name: ProtocolVersionNumber
       Type: int32
+    - Name: ProcessKey
+      Type: int32
+      If: 'T.ProtocolVersionNumber == 80877102'
+    - Name: SecretKey
+      Type: int32
+      If: 'T.ProtocolVersionNumber == 80877102'
     - Name: Parameters
+      If: 'T.ProtocolVersionNumber == 196608'
       Struct:
         Fields:
           - Name: Name
@@ -116,4 +123,4 @@ StartupMessage:
 Sync:
   Identifier: 'S'
 Terminate:
-  Identifier: 'X'
\ No newline at end of file
+  Identifier: 'X'
-- 
GitLab