diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 629a3c48..80c7f126 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,7 +1,12 @@ # global code owners -* @TimSatke @tomarrell +* @TimSatke @tomarrell +internal/database/storage/btree @tomarrell +internal/parser @TimSatke @SUMUKHA-PK +internal/raft @SUMUKHA-PK +internal/raft/cluster @TimSatke +internal/raft/message @TimSatke internal/compiler @TimSatke internal/database/storage/btree @tomarrell internal/network @TimSatke -internal/parser @TimSatke @SUMUKHA-PK \ No newline at end of file +internal/parser @TimSatke @SUMUKHA-PK diff --git a/cmd/lbadd/main.go b/cmd/lbadd/main.go index ce3ed6ce..0a14c2d8 100644 --- a/cmd/lbadd/main.go +++ b/cmd/lbadd/main.go @@ -160,7 +160,7 @@ func startNode(cmd *cobra.Command, args []string) { if err := node.ListenAndServe(cmd.Context(), addr); err != nil { log.Error(). Err(err). - Msg("listen and serve") + Msg("open") os.Exit(ExitAbnormal) } } diff --git a/go.mod b/go.mod index e440c051..0fec7962 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/tomarrell/lbadd go 1.13 require ( + github.com/golang/protobuf v1.4.2 github.com/google/go-cmp v0.5.1 github.com/kr/text v0.2.0 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect @@ -10,11 +11,11 @@ require ( github.com/rs/zerolog v1.19.0 github.com/spf13/afero v1.3.2 github.com/spf13/cobra v1.0.0 - github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.6.1 - golang.org/x/net v0.0.0-20200505041828-1ed23360d12c - golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a + golang.org/x/net v0.0.0-20200707034311-ab3426394381 + golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 golang.org/x/text v0.3.3 - golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed + google.golang.org/protobuf v1.25.0 + gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 9592c869..f065ec70 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -20,7 +21,8 @@ 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -34,15 +36,28 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er 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.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 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 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 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -53,37 +68,32 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -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/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -98,7 +108,6 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.3.2 h1:GDarE4TJQI52kYSbSAmLiId1Elfj+xgSDqrUZxFhxlU= github.com/spf13/afero v1.3.2/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= @@ -106,15 +115,10 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -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/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 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.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -126,7 +130,7 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -135,37 +139,36 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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/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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +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 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +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-20181114220301-adae6a3d119a/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-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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200505041828-1ed23360d12c h1:zJ0mtu4jCalhKg6Oaukv6iIkb+cOvDrajDH9DH46Q4M= -golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -176,29 +179,47 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190828213141-aed303cbaa74 h1:4cFkmztxtMslUX2SctSl+blCyXfpzhGOy9LhKAqSMA4= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc h1:6m2YO+AmBApbUOmhsghW+IfRyZOY4My4UYvQQrEpHfY= -golang.org/x/tools v0.0.0-20200521211927-2b542361a4fc/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed h1:+qzWo37K31KxduIYaBeMqJ8MUOyTayOQKpH9aDPLMSY= +golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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-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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +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.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 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/internal/compiler/command/command.go b/internal/compiler/command/command.go index 9787e089..ba2fdb73 100644 --- a/internal/compiler/command/command.go +++ b/internal/compiler/command/command.go @@ -18,9 +18,9 @@ var _ Command = (*DropIndex)(nil) var _ Command = (*DropTrigger)(nil) var _ Command = (*DropView)(nil) var _ Command = (*Update)(nil) -var _ Command = (*Insert)(nil) var _ Command = (*Join)(nil) var _ Command = (*Limit)(nil) +var _ Command = (*Insert)(nil) // Command describes a structure that can be executed by the database executor. // Instead of using bytecode, we use a hierarchical structure for the executor. diff --git a/internal/network/errors.go b/internal/network/error.go similarity index 100% rename from internal/network/errors.go rename to internal/network/error.go diff --git a/internal/network/example_test.go b/internal/network/example_test.go index e9a6c0ab..a184200f 100644 --- a/internal/network/example_test.go +++ b/internal/network/example_test.go @@ -6,6 +6,7 @@ import ( "log" "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/id" "github.com/tomarrell/lbadd/internal/network" ) @@ -26,7 +27,8 @@ func ExampleServer() { <-srv.Listening() // wait for the server to come up - client, _ := network.DialTCP(ctx, ":59513") + clientID := id.Create() + client, _ := network.DialTCP(ctx, clientID, ":59513") defer func() { _ = client.Close() }() diff --git a/internal/network/id.go b/internal/network/id.go deleted file mode 100644 index 99b4c1d2..00000000 --- a/internal/network/id.go +++ /dev/null @@ -1,54 +0,0 @@ -package network - -import ( - "fmt" - "log" - "math/rand" - "sync" - "time" - - "github.com/oklog/ulid" -) - -var _ ID = (*id)(nil) - -type id ulid.ULID - -var ( - lock sync.Mutex - randSource = rand.New(rand.NewSource(time.Now().UnixNano())) - entropy = ulid.Monotonic(randSource, 0) -) - -func createID() ID { - lock.Lock() - defer lock.Unlock() - - genID, err := ulid.New(ulid.Now(), entropy) - if err != nil { - // For this to happen, the random module would have to fail. Since we - // use Go's pseudo RNG, which just jumps around a few numbers, instead - // of using crypto/rand, and we also made this function safe for - // concurrent use, this is nearly impossible to happen. However, with - // the current version of oklog/ulid v1.3.1, this will also break after - // 2121-04-11 11:53:25.01172576 UTC. - log.Fatal(fmt.Errorf("new ulid: %w", err)) - } - return id(genID) -} - -func parseID(idBytes []byte) (ID, error) { - parsed, err := ulid.Parse(string(idBytes)) - if err != nil { - return nil, fmt.Errorf("parse: %w", err) - } - return id(parsed), nil -} - -func (id id) String() string { - return ulid.ULID(id).String() -} - -func (id id) Bytes() []byte { - return []byte(id.String()) -} diff --git a/internal/network/id_test.go b/internal/network/id_test.go deleted file mode 100644 index 8510026c..00000000 --- a/internal/network/id_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package network - -import "testing" - -func TestIDThreadSafe(t *testing.T) { - // This is sufficient for the race detector to detect a race if createID is - // not safe for concurrent use. - for i := 0; i < 5; i++ { - go func() { - _ = createID() - }() - } -} diff --git a/internal/network/mocks/conn.go b/internal/network/mocks/conn.go new file mode 100644 index 00000000..9b4fd136 --- /dev/null +++ b/internal/network/mocks/conn.go @@ -0,0 +1,82 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + id "github.com/tomarrell/lbadd/internal/id" +) + +// Conn is an autogenerated mock type for the Conn type +type Conn struct { + mock.Mock +} + +// Close provides a mock function with given fields: +func (_m *Conn) Close() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Receive provides a mock function with given fields: _a0 +func (_m *Conn) Receive(_a0 context.Context) ([]byte, error) { + ret := _m.Called(_a0) + + var r0 []byte + if rf, ok := ret.Get(0).(func(context.Context) []byte); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RemoteID provides a mock function with given fields: +func (_m *Conn) RemoteID() id.ID { + ret := _m.Called() + + var r0 id.ID + if rf, ok := ret.Get(0).(func() id.ID); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(id.ID) + } + } + + return r0 +} + +// Send provides a mock function with given fields: _a0, _a1 +func (_m *Conn) Send(_a0 context.Context, _a1 []byte) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []byte) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} diff --git a/internal/network/mocks/doc.go b/internal/network/mocks/doc.go new file mode 100644 index 00000000..35abed3d --- /dev/null +++ b/internal/network/mocks/doc.go @@ -0,0 +1,2 @@ +// Package mocks provides generated mock implementations for easy testing. +package mocks diff --git a/internal/network/server.go b/internal/network/server.go index 99b659b2..89053789 100644 --- a/internal/network/server.go +++ b/internal/network/server.go @@ -2,9 +2,10 @@ package network import ( "context" - "fmt" "io" "net" + + "github.com/tomarrell/lbadd/internal/id" ) // ConnHandler is a handler function for handling new connections. It will be @@ -29,11 +30,16 @@ type Server interface { // Addr returns the address that this server is listening to. Addr() net.Addr + // OwnID returns the ID of this server. The remote ID of any connection is + // the own ID of another server. + OwnID() id.ID // OnConnect sets a callback that will be executed whenever a new connection // connects to this server. OnConnect(ConnHandler) } +//go:generate mockery -case=snake -name=Conn + // Conn describes a network connection. One can send a message with Conn.Send, // and receive one with Conn.Receive. Unlike an io.Writer, the data that is // passed into Send is guaranteed to be returned in a single Receive call on the @@ -42,9 +48,8 @@ type Server interface { type Conn interface { io.Closer - // ID returns the ID of this connection. It can be used to uniquely identify - // this connection globally. - ID() ID + // RemoteID returns the own ID of the server that this connection points to. + RemoteID() id.ID // Send sends the given payload to the remote part of this connection. The // message will not be chunked, and can be read with a single call to // Conn.Receive. @@ -53,10 +58,3 @@ type Conn interface { // is a byte slice that was sent with a single call to Conn.Send. Receive(context.Context) ([]byte, error) } - -// ID describes an identifier that is used for connections. An ID has to be -// unique application-wide. IDs must not be re-used. -type ID interface { - fmt.Stringer - Bytes() []byte -} diff --git a/internal/network/tcp_conn.go b/internal/network/tcp_conn.go index 13021444..fd8bf1a6 100644 --- a/internal/network/tcp_conn.go +++ b/internal/network/tcp_conn.go @@ -5,8 +5,10 @@ import ( "fmt" "net" "sync" + "sync/atomic" "time" + "github.com/tomarrell/lbadd/internal/id" "golang.org/x/net/context" "golang.org/x/sync/errgroup" ) @@ -22,8 +24,8 @@ var ( var _ Conn = (*tcpConn)(nil) type tcpConn struct { - id ID - closed bool + remoteID id.ID + closed int32 readLock sync.Mutex writeLock sync.Mutex @@ -32,7 +34,7 @@ type tcpConn struct { // DialTCP dials to the given address, assuming a TCP network. The returned Conn // is ready to use. -func DialTCP(ctx context.Context, addr string) (Conn, error) { +func DialTCP(ctx context.Context, ownID id.ID, addr string) (Conn, error) { // dial the remote endpoint var d net.Dialer conn, err := d.DialContext(ctx, "tcp", addr) @@ -43,38 +45,50 @@ func DialTCP(ctx context.Context, addr string) (Conn, error) { // create a new connection object tcpConn := newTCPConn(conn) - // receive the connection ID from the remote endpoint and apply it - myID, err := tcpConn.Receive(ctx) + // receive the remote ID from the remote endpoint and apply it + remoteID, err := tcpConn.Receive(ctx) if err != nil { _ = tcpConn.Close() - return nil, fmt.Errorf("receive ID: %w", err) + return nil, fmt.Errorf("receive remote ID: %w", err) } - parsedID, err := parseID(myID) + parsedID, err := id.Parse(remoteID) if err != nil { _ = tcpConn.Close() - return nil, fmt.Errorf("parse ID: %w", err) + return nil, fmt.Errorf("parse remote ID: %w", err) + } + tcpConn.remoteID = parsedID + + // send own ID to remote endpoint + err = tcpConn.Send(ctx, ownID.Bytes()) + if err != nil { + _ = tcpConn.Close() + return nil, fmt.Errorf("send own ID: %w", err) } - tcpConn.id = parsedID // return the connection object return tcpConn, nil } +// NewTCPConn wraps the underlying connection into a tcpConn. +func NewTCPConn(underlying net.Conn) Conn { + return newTCPConn(underlying) +} + func newTCPConn(underlying net.Conn) *tcpConn { - id := createID() + id := id.Create() conn := &tcpConn{ - id: id, + remoteID: id, underlying: underlying, } return conn } -func (c *tcpConn) ID() ID { - return c.id +func (c *tcpConn) RemoteID() id.ID { + return c.remoteID } func (c *tcpConn) Send(ctx context.Context, payload []byte) error { - if c.closed { + if atomic.LoadInt32(&c.closed) == 1 { return ErrClosed } @@ -137,7 +151,7 @@ func (c *tcpConn) sendAsync(payload []byte) chan error { } func (c *tcpConn) Receive(ctx context.Context) ([]byte, error) { - if c.closed { + if atomic.LoadInt32(&c.closed) == 1 { return nil, ErrClosed } @@ -202,7 +216,7 @@ func (c *tcpConn) receiveAsync() chan interface{} { } func (c *tcpConn) Close() error { - c.closed = true + atomic.StoreInt32(&c.closed, 1) // release all resources ctx := context.Background() diff --git a/internal/network/tcp_conn_test.go b/internal/network/tcp_conn_test.go index 19a74b5c..cf20f8ad 100644 --- a/internal/network/tcp_conn_test.go +++ b/internal/network/tcp_conn_test.go @@ -9,6 +9,7 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/id" ) func TestTCPConnSendReceive(t *testing.T) { @@ -17,7 +18,7 @@ func TestTCPConnSendReceive(t *testing.T) { defer cancel() conn1, conn2 := net.Pipe() - tcpConn1, tcpConn2 := newTCPConn(conn1), newTCPConn(conn2) + tcpConn1, tcpConn2 := NewTCPConn(conn1), NewTCPConn(conn2) payload := []byte("Hello, World!") recv := make([]byte, len(payload)) @@ -47,16 +48,23 @@ func TestDialTCP(t *testing.T) { lis, err := net.Listen("tcp", ":0") assert.NoError(err) + clientID := id.Create() + srvID := id.Create() var wg sync.WaitGroup wg.Add(1) - var srvConnID string go func() { conn, err := lis.Accept() assert.NoError(err) - tcpConn := newTCPConn(conn) - srvConnID = tcpConn.ID().String() - assert.NoError(tcpConn.Send(ctx, tcpConn.ID().Bytes())) + // default handshake + tcpConn := NewTCPConn(conn) + assert.NoError(tcpConn.Send(ctx, srvID.Bytes())) // send server ID + recvID, err := tcpConn.Receive(ctx) // receive client ID + assert.NoError(err) // + parsedID, err := id.Parse(recvID) // parse client ID + assert.NoError(err) // + assert.Equal(clientID.String(), parsedID.String()) // parsed ID must be equal to actual client ID + assert.NoError(tcpConn.Send(ctx, payload)) wg.Done() @@ -64,10 +72,10 @@ func TestDialTCP(t *testing.T) { port := lis.Addr().(*net.TCPAddr).Port - conn, err := DialTCP(ctx, ":"+strconv.Itoa(port)) + conn, err := DialTCP(ctx, clientID, ":"+strconv.Itoa(port)) assert.NoError(err) defer func() { assert.NoError(conn.Close()) }() - assert.Equal(srvConnID, conn.ID().String()) + assert.Equal(srvID.String(), conn.RemoteID().String()) recv, err := conn.Receive(ctx) assert.NoError(err) @@ -82,7 +90,7 @@ func TestTCPConnWriteContext(t *testing.T) { defer cancel() conn1, conn2 := net.Pipe() - tcpConn1, _ := newTCPConn(conn1), newTCPConn(conn2) + tcpConn1, _ := NewTCPConn(conn1), NewTCPConn(conn2) err := tcpConn1.Send(ctx, []byte("Hello")) // will not be able to write within 10ms, because noone is reading assert.Equal(ErrTimeout, err) @@ -94,7 +102,7 @@ func TestTCPConnReadContext(t *testing.T) { defer cancel() conn1, conn2 := net.Pipe() - tcpConn1, _ := newTCPConn(conn1), newTCPConn(conn2) + tcpConn1, _ := NewTCPConn(conn1), NewTCPConn(conn2) data, err := tcpConn1.Receive(ctx) // will not be able to receive within 10ms, because noone is writing assert.Equal(ErrTimeout, err) diff --git a/internal/network/tcp_server.go b/internal/network/tcp_server.go index 097c0974..82571b1c 100644 --- a/internal/network/tcp_server.go +++ b/internal/network/tcp_server.go @@ -3,9 +3,11 @@ package network import ( "fmt" "net" + "sync" "time" "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/id" "golang.org/x/net/context" "golang.org/x/sync/errgroup" ) @@ -19,18 +21,27 @@ type tcpServer struct { listening chan struct{} lis net.Listener + ownID id.ID + onConnect ConnHandler + // lock needed for atomic write on onConnect. + mu sync.Mutex } // NewTCPServer creates a new ready to use TCP server that uses the given // logger. func NewTCPServer(log zerolog.Logger) Server { return &tcpServer{ - log: log, + log: log.With().Str("server", "tcp").Logger(), listening: make(chan struct{}), + ownID: id.Create(), } } +func (s *tcpServer) OwnID() id.ID { + return s.ownID +} + func (s *tcpServer) Open(addr string) error { if s.open { return ErrOpen @@ -64,6 +75,8 @@ func (s *tcpServer) Addr() net.Addr { } func (s *tcpServer) OnConnect(h ConnHandler) { + s.mu.Lock() + defer s.mu.Unlock() s.onConnect = h } @@ -73,7 +86,12 @@ func (s *tcpServer) Close() error { // release all resources ctx := context.Background() errs, _ := errgroup.WithContext(ctx) - errs.Go(s.lis.Close) + errs.Go(func() error { + if s.lis == nil { + return nil + } + return s.lis.Close() + }) return errs.Wait() } @@ -108,7 +126,8 @@ func (s *tcpServer) handleIncomingNetConn(conn net.Conn) { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() - err := tcpConn.Send(ctx, tcpConn.id.Bytes()) + // send own ID to client + err := tcpConn.Send(ctx, s.ownID.Bytes()) if err != nil { s.log.Error(). Err(err). @@ -117,6 +136,25 @@ func (s *tcpServer) handleIncomingNetConn(conn net.Conn) { return } + // receive the client ID from the remote endpoint and apply it + remoteID, err := tcpConn.Receive(ctx) + if err != nil { + s.log.Error(). + Err(err). + Msg("receive remote ID") + _ = tcpConn.Close() + return + } + parsedID, err := id.Parse(remoteID) + if err != nil { + s.log.Error(). + Err(err). + Msg("parse remote ID") + _ = tcpConn.Close() + return + } + tcpConn.remoteID = parsedID + if s.onConnect != nil { s.onConnect(tcpConn) } diff --git a/internal/network/tcp_server_test.go b/internal/network/tcp_server_test.go new file mode 100644 index 00000000..f34562ed --- /dev/null +++ b/internal/network/tcp_server_test.go @@ -0,0 +1,68 @@ +package network_test + +import ( + "context" + "testing" + "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" +) + +// TestTCPServerHandshake ensures that the server logon handshake with DialTCP +// works correctly. The handshake is responsible for sending the client the +// server ID, and then receive the client ID and remember it in its connection. +// After the handshake, the ID of the connection on the server side must be +// equal to the client ID, and the remote ID of the connection created with +// DialTCP must be equal to the server ID. +func TestTCPServerHandshake(t *testing.T) { + assert := assert.New(t) + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + // create the server + server := network.NewTCPServer(zerolog.Nop()) + defer func() { _ = server.Close() }() + + serverID := server.OwnID() + assert.NotNil(serverID) + serverConns := make(chan network.Conn) + server.OnConnect(func(conn network.Conn) { + serverConns <- conn + }) + + // open the server in separate goroutine + go func() { + err := server.Open(":0") + assert.NoError(err) + }() + + // enforce timeout for server open + select { + case <-ctx.Done(): + _ = server.Close() + t.Error("timeout") + case <-server.Listening(): + } + + t.Logf("server address: %v", server.Addr()) + + // dial the server + conn1ID := id.Create() // create a connection ID + conn1, err := network.DialTCP(ctx, conn1ID, server.Addr().String()) + assert.NoError(err) + + // check the client side connection + assert.Equal(serverID, conn1.RemoteID()) // ensure that the remote ID of this connection is equal to the own ID of the server + + // check the server side connections + select { + case conn := <-serverConns: + assert.Equal(conn1ID, conn.RemoteID()) + case <-ctx.Done(): + assert.Fail("timeout") + } +} diff --git a/internal/network/test_framework.go b/internal/network/test_framework.go new file mode 100644 index 00000000..557f5362 --- /dev/null +++ b/internal/network/test_framework.go @@ -0,0 +1,28 @@ +package network + +import ( + "github.com/rs/zerolog" +) + +// TestNode describes a single node and all its connections. +type TestNode struct { + Node Server + Conns []Conn +} + +// NewTestNode returns a ready to use node with no connections associated. +func NewTestNode(IP, port string, log zerolog.Logger) (tNode *TestNode, err error) { + node := NewTCPServer(log) + go func() { + err = node.Open(IP + ":" + port) + }() + + if err != nil { + return + } + + <-node.Listening() + return &TestNode{ + Node: node, + }, nil +} diff --git a/internal/node/error.go b/internal/node/error.go new file mode 100644 index 00000000..75abb92a --- /dev/null +++ b/internal/node/error.go @@ -0,0 +1,18 @@ +package node + +// Error is a helper type for creating constant errors. +type Error string + +func (e Error) Error() string { return string(e) } + +const ( + // ErrOpen indicates, that the component was already opened, and it is + // unable to be opened another time. + ErrOpen Error = "already open" + // ErrClosed indicates, that the component is already closed, and it cannot + // be used anymore. + ErrClosed Error = "already closed" + // ErrTimeout indicates, that a the operation took longer than allowed. + // Maybe there was a deadline from a context. + ErrTimeout Error = "timeout" +) diff --git a/internal/node/node.go b/internal/node/node.go index f92a3a86..2761b46d 100644 --- a/internal/node/node.go +++ b/internal/node/node.go @@ -5,14 +5,22 @@ import ( "fmt" "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/engine" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft" + "github.com/tomarrell/lbadd/internal/raft/cluster" + "github.com/tomarrell/lbadd/internal/raft/message" + "golang.org/x/sync/errgroup" ) -// Node is a database node. -// -// m := node.New(log) -// err := m.ListenAndServe(ctx, ":34213") +// Node is a database node. It uses an underlying raft.Server to communicate +// with other nodes, if any. type Node struct { - log zerolog.Logger + log zerolog.Logger + engine engine.Engine + + raft raft.Server + cluster cluster.Cluster } // New creates a new node that is executing commands on the given executor. @@ -26,9 +34,85 @@ func New(log zerolog.Logger) *Node { // be used to stop the server, since there is no stop function. Canceling the // context or a context timeout will cause the server to attempt a graceful // shutdown. -func (m *Node) ListenAndServe(ctx context.Context, addr string) error { - m.log.Info(). +func (n *Node) ListenAndServe(ctx context.Context, addr string) error { + n.log.Info(). Str("addr", addr). Msg("listen and serve") return fmt.Errorf("unimplemented") } + +// Open opens a new cluster, making this node the only node in the cluster. +// Other clusters can connect to the given address and perform the implemented +// handshake, in order to become nodes in the cluster. +func (n *Node) Open(ctx context.Context, addr string) error { + n.log.Info(). + Str("addr", addr). + Msg("open") + + if err := n.openCluster(ctx, addr); err != nil { + return fmt.Errorf("open cluster: %w", err) + } + + return n.startNode(ctx) +} + +// Close closes the node, starting with the underlying raft server, then the +// cluster, then the executor. +func (n *Node) Close() error { + ctx := context.TODO() + errs, _ := errgroup.WithContext(ctx) + errs.Go(n.raft.Close) + errs.Go(n.cluster.Close) + errs.Go(n.engine.Close) + return errs.Wait() +} + +func (n *Node) openCluster(ctx context.Context, addr string) error { + if n.cluster != nil { + return ErrOpen + } + + cluster := cluster.NewTCPCluster(n.log) + cluster.OnConnect(n.performLogonHandshake) + if err := cluster.Open(ctx, addr); err != nil { + return fmt.Errorf("open cluster: %w", err) + } + return nil +} + +func (n *Node) performLogonHandshake(cluster cluster.Cluster, conn network.Conn) { + n.log.Debug(). + Str("conn-id", conn.RemoteID().String()). + Msg("perform handshake") + + n.log.Info(). + Str("conn-id", conn.RemoteID().String()). + Msg("connected") + + cluster.AddConnection(conn) +} + +func (n *Node) startNode(ctx context.Context) error { + n.raft = raft.NewServer(n.log, n.cluster) + n.raft.OnReplication(n.replicate) + + return n.raft.Start(ctx) +} + +// replicate returns the number of commands that were executed from the +// given slice of commands. -1 is returned if no commands were executed. +func (n *Node) replicate(input []*message.Command) int { + for i := range input { + cmd := message.ConvertMessageToCommand(input[i]) + + // Link to the engine's executor must be added here. + _, err := n.engine.Evaluate(cmd) + if err != nil { + n.log.Error(). + Err(err). + Msg("failed to replicate input: execute") + return i - 1 + } + } + return len(input) +} diff --git a/internal/parser/scanner/ruleset/ruleset_default_keyword_trie.go b/internal/parser/scanner/ruleset/ruleset_default_keyword_trie.go index dab26bc4..e24fadcf 100644 --- a/internal/parser/scanner/ruleset/ruleset_default_keyword_trie.go +++ b/internal/parser/scanner/ruleset/ruleset_default_keyword_trie.go @@ -9,8 +9,8 @@ func defaultKeywordsRule(s RuneScanner) (token.Type, bool) { if !ok { return token.Unknown, false } - peek, noEof := s.Lookahead() - if noEof && defaultLiteral.Matches(peek) { // keywords must be terminated with a whitespace + peek, noEOF := s.Lookahead() + if noEOF && defaultLiteral.Matches(peek) { // keywords must be terminated with a whitespace return token.Unknown, false } return tok, ok @@ -22,95 +22,72 @@ func scanKeyword(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordA(s) - case 'B', 'b': s.ConsumeRune() return scanKeywordB(s) - case 'C', 'c': s.ConsumeRune() return scanKeywordC(s) - case 'D', 'd': s.ConsumeRune() return scanKeywordD(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordE(s) - case 'F', 'f': s.ConsumeRune() return scanKeywordF(s) - case 'G', 'g': s.ConsumeRune() return scanKeywordG(s) - case 'H', 'h': s.ConsumeRune() return scanKeywordH(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordI(s) - case 'J', 'j': s.ConsumeRune() return scanKeywordJ(s) - case 'K', 'k': s.ConsumeRune() return scanKeywordK(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordL(s) - case 'M', 'm': s.ConsumeRune() return scanKeywordM(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordN(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordO(s) - case 'P', 'p': s.ConsumeRune() return scanKeywordP(s) - case 'Q', 'q': s.ConsumeRune() return scanKeywordQ(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordR(s) - case 'S', 's': s.ConsumeRune() return scanKeywordS(s) - case 'T', 't': s.ConsumeRune() return scanKeywordT(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordU(s) - case 'V', 'v': s.ConsumeRune() return scanKeywordV(s) - case 'W', 'w': s.ConsumeRune() return scanKeywordW(s) @@ -124,39 +101,30 @@ func scanKeywordA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordAB(s) - case 'C', 'c': s.ConsumeRune() return scanKeywordAC(s) - case 'D', 'd': s.ConsumeRune() return scanKeywordAD(s) - case 'F', 'f': s.ConsumeRune() return scanKeywordAF(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordAL(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordAN(s) - case 'S', 's': s.ConsumeRune() return scanKeywordAS(s) - case 'T', 't': s.ConsumeRune() return scanKeywordAT(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordAU(s) @@ -170,7 +138,6 @@ func scanKeywordAB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordABO(s) @@ -184,7 +151,6 @@ func scanKeywordABO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordABOR(s) @@ -198,7 +164,6 @@ func scanKeywordABOR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordABORT(s) @@ -216,7 +181,6 @@ func scanKeywordAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordACT(s) @@ -230,7 +194,6 @@ func scanKeywordACT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordACTI(s) @@ -244,7 +207,6 @@ func scanKeywordACTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordACTIO(s) @@ -258,7 +220,6 @@ func scanKeywordACTIO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordACTION(s) @@ -276,7 +237,6 @@ func scanKeywordAD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordADD(s) @@ -294,7 +254,6 @@ func scanKeywordAF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordAFT(s) @@ -308,7 +267,6 @@ func scanKeywordAFT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordAFTE(s) @@ -322,7 +280,6 @@ func scanKeywordAFTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordAFTER(s) @@ -340,15 +297,12 @@ func scanKeywordAL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordALL(s) - case 'T', 't': s.ConsumeRune() return scanKeywordALT(s) - case 'W', 'w': s.ConsumeRune() return scanKeywordALW(s) @@ -366,7 +320,6 @@ func scanKeywordALT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordALTE(s) @@ -380,7 +333,6 @@ func scanKeywordALTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordALTER(s) @@ -398,7 +350,6 @@ func scanKeywordALW(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordALWA(s) @@ -412,7 +363,6 @@ func scanKeywordALWA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordALWAY(s) @@ -426,7 +376,6 @@ func scanKeywordALWAY(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordALWAYS(s) @@ -444,11 +393,9 @@ func scanKeywordAN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordANA(s) - case 'D', 'd': s.ConsumeRune() return scanKeywordAND(s) @@ -462,7 +409,6 @@ func scanKeywordANA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordANAL(s) @@ -476,7 +422,6 @@ func scanKeywordANAL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordANALY(s) @@ -490,7 +435,6 @@ func scanKeywordANALY(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Z', 'z': s.ConsumeRune() return scanKeywordANALYZ(s) @@ -504,7 +448,6 @@ func scanKeywordANALYZ(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordANALYZE(s) @@ -526,7 +469,6 @@ func scanKeywordAS(s RuneScanner) (token.Type, bool) { return token.KeywordAs, true } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordASC(s) @@ -544,7 +486,6 @@ func scanKeywordAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordATT(s) @@ -558,7 +499,6 @@ func scanKeywordATT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordATTA(s) @@ -572,7 +512,6 @@ func scanKeywordATTA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordATTAC(s) @@ -586,7 +525,6 @@ func scanKeywordATTAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordATTACH(s) @@ -604,7 +542,6 @@ func scanKeywordAU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordAUT(s) @@ -618,7 +555,6 @@ func scanKeywordAUT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordAUTO(s) @@ -632,7 +568,6 @@ func scanKeywordAUTO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordAUTOI(s) @@ -646,7 +581,6 @@ func scanKeywordAUTOI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordAUTOIN(s) @@ -660,7 +594,6 @@ func scanKeywordAUTOIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordAUTOINC(s) @@ -674,7 +607,6 @@ func scanKeywordAUTOINC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordAUTOINCR(s) @@ -688,7 +620,6 @@ func scanKeywordAUTOINCR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordAUTOINCRE(s) @@ -702,7 +633,6 @@ func scanKeywordAUTOINCRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordAUTOINCREM(s) @@ -716,7 +646,6 @@ func scanKeywordAUTOINCREM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordAUTOINCREME(s) @@ -730,7 +659,6 @@ func scanKeywordAUTOINCREME(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordAUTOINCREMEN(s) @@ -744,7 +672,6 @@ func scanKeywordAUTOINCREMEN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordAUTOINCREMENT(s) @@ -762,11 +689,9 @@ func scanKeywordB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordBE(s) - case 'Y', 'y': s.ConsumeRune() return scanKeywordBY(s) @@ -780,15 +705,12 @@ func scanKeywordBE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordBEF(s) - case 'G', 'g': s.ConsumeRune() return scanKeywordBEG(s) - case 'T', 't': s.ConsumeRune() return scanKeywordBET(s) @@ -802,7 +724,6 @@ func scanKeywordBEF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordBEFO(s) @@ -816,7 +737,6 @@ func scanKeywordBEFO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordBEFOR(s) @@ -830,7 +750,6 @@ func scanKeywordBEFOR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordBEFORE(s) @@ -848,7 +767,6 @@ func scanKeywordBEG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordBEGI(s) @@ -862,7 +780,6 @@ func scanKeywordBEGI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordBEGIN(s) @@ -880,7 +797,6 @@ func scanKeywordBET(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'W', 'w': s.ConsumeRune() return scanKeywordBETW(s) @@ -894,7 +810,6 @@ func scanKeywordBETW(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordBETWE(s) @@ -908,7 +823,6 @@ func scanKeywordBETWE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordBETWEE(s) @@ -922,7 +836,6 @@ func scanKeywordBETWEE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordBETWEEN(s) @@ -944,23 +857,18 @@ func scanKeywordC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCA(s) - case 'H', 'h': s.ConsumeRune() return scanKeywordCH(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordCO(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordCR(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordCU(s) @@ -974,7 +882,6 @@ func scanKeywordCA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordCAS(s) @@ -988,15 +895,12 @@ func scanKeywordCAS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordCASC(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordCASE(s) - case 'T', 't': s.ConsumeRune() return scanKeywordCAST(s) @@ -1010,7 +914,6 @@ func scanKeywordCASC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCASCA(s) @@ -1024,7 +927,6 @@ func scanKeywordCASCA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordCASCAD(s) @@ -1038,7 +940,6 @@ func scanKeywordCASCAD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCASCADE(s) @@ -1064,7 +965,6 @@ func scanKeywordCH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCHE(s) @@ -1078,7 +978,6 @@ func scanKeywordCHE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordCHEC(s) @@ -1092,7 +991,6 @@ func scanKeywordCHEC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'K', 'k': s.ConsumeRune() return scanKeywordCHECK(s) @@ -1110,15 +1008,12 @@ func scanKeywordCO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordCOL(s) - case 'M', 'm': s.ConsumeRune() return scanKeywordCOM(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordCON(s) @@ -1132,11 +1027,9 @@ func scanKeywordCOL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordCOLL(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordCOLU(s) @@ -1150,7 +1043,6 @@ func scanKeywordCOLL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCOLLA(s) @@ -1164,7 +1056,6 @@ func scanKeywordCOLLA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCOLLAT(s) @@ -1178,7 +1069,6 @@ func scanKeywordCOLLAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCOLLATE(s) @@ -1196,7 +1086,6 @@ func scanKeywordCOLU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordCOLUM(s) @@ -1210,7 +1099,6 @@ func scanKeywordCOLUM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordCOLUMN(s) @@ -1228,7 +1116,6 @@ func scanKeywordCOM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordCOMM(s) @@ -1242,7 +1129,6 @@ func scanKeywordCOMM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordCOMMI(s) @@ -1256,7 +1142,6 @@ func scanKeywordCOMMI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCOMMIT(s) @@ -1274,11 +1159,9 @@ func scanKeywordCON(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordCONF(s) - case 'S', 's': s.ConsumeRune() return scanKeywordCONS(s) @@ -1292,7 +1175,6 @@ func scanKeywordCONF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordCONFL(s) @@ -1306,7 +1188,6 @@ func scanKeywordCONFL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordCONFLI(s) @@ -1320,7 +1201,6 @@ func scanKeywordCONFLI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordCONFLIC(s) @@ -1334,7 +1214,6 @@ func scanKeywordCONFLIC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCONFLICT(s) @@ -1352,7 +1231,6 @@ func scanKeywordCONS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCONST(s) @@ -1366,7 +1244,6 @@ func scanKeywordCONST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordCONSTR(s) @@ -1380,7 +1257,6 @@ func scanKeywordCONSTR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCONSTRA(s) @@ -1394,7 +1270,6 @@ func scanKeywordCONSTRA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordCONSTRAI(s) @@ -1408,7 +1283,6 @@ func scanKeywordCONSTRAI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordCONSTRAIN(s) @@ -1422,7 +1296,6 @@ func scanKeywordCONSTRAIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCONSTRAINT(s) @@ -1440,11 +1313,9 @@ func scanKeywordCR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCRE(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordCRO(s) @@ -1458,7 +1329,6 @@ func scanKeywordCRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCREA(s) @@ -1472,7 +1342,6 @@ func scanKeywordCREA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCREAT(s) @@ -1486,7 +1355,6 @@ func scanKeywordCREAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCREATE(s) @@ -1504,7 +1372,6 @@ func scanKeywordCRO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordCROS(s) @@ -1518,7 +1385,6 @@ func scanKeywordCROS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordCROSS(s) @@ -1536,7 +1402,6 @@ func scanKeywordCU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordCUR(s) @@ -1550,7 +1415,6 @@ func scanKeywordCUR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordCURR(s) @@ -1564,7 +1428,6 @@ func scanKeywordCURR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCURRE(s) @@ -1578,7 +1441,6 @@ func scanKeywordCURRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordCURREN(s) @@ -1592,7 +1454,6 @@ func scanKeywordCURREN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCURRENT(s) @@ -1606,7 +1467,6 @@ func scanKeywordCURRENT(s RuneScanner) (token.Type, bool) { return token.KeywordCurrent, true } switch next { - case '_': s.ConsumeRune() return scanKeywordCURRENTx(s) @@ -1620,11 +1480,9 @@ func scanKeywordCURRENTx(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordCURRENTxD(s) - case 'T', 't': s.ConsumeRune() return scanKeywordCURRENTxT(s) @@ -1638,7 +1496,6 @@ func scanKeywordCURRENTxD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCURRENTxDA(s) @@ -1652,7 +1509,6 @@ func scanKeywordCURRENTxDA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCURRENTxDAT(s) @@ -1666,7 +1522,6 @@ func scanKeywordCURRENTxDAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCURRENTxDATE(s) @@ -1684,7 +1539,6 @@ func scanKeywordCURRENTxT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordCURRENTxTI(s) @@ -1698,7 +1552,6 @@ func scanKeywordCURRENTxTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordCURRENTxTIM(s) @@ -1712,7 +1565,6 @@ func scanKeywordCURRENTxTIM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordCURRENTxTIME(s) @@ -1726,7 +1578,6 @@ func scanKeywordCURRENTxTIME(s RuneScanner) (token.Type, bool) { return token.KeywordCurrentTime, true } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordCURRENTxTIMES(s) @@ -1740,7 +1591,6 @@ func scanKeywordCURRENTxTIMES(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordCURRENTxTIMEST(s) @@ -1754,7 +1604,6 @@ func scanKeywordCURRENTxTIMEST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordCURRENTxTIMESTA(s) @@ -1768,7 +1617,6 @@ func scanKeywordCURRENTxTIMESTA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordCURRENTxTIMESTAM(s) @@ -1782,7 +1630,6 @@ func scanKeywordCURRENTxTIMESTAM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordCURRENTxTIMESTAMP(s) @@ -1800,23 +1647,18 @@ func scanKeywordD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordDE(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordDI(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordDO(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordDR(s) @@ -1830,7 +1672,6 @@ func scanKeywordDA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordDAT(s) @@ -1844,7 +1685,6 @@ func scanKeywordDAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDATA(s) @@ -1858,7 +1698,6 @@ func scanKeywordDATA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordDATAB(s) @@ -1872,7 +1711,6 @@ func scanKeywordDATAB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDATABA(s) @@ -1886,7 +1724,6 @@ func scanKeywordDATABA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordDATABAS(s) @@ -1900,7 +1737,6 @@ func scanKeywordDATABAS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordDATABASE(s) @@ -1918,19 +1754,15 @@ func scanKeywordDE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordDEF(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordDEL(s) - case 'S', 's': s.ConsumeRune() return scanKeywordDES(s) - case 'T', 't': s.ConsumeRune() return scanKeywordDET(s) @@ -1944,11 +1776,9 @@ func scanKeywordDEF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDEFA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordDEFE(s) @@ -1962,7 +1792,6 @@ func scanKeywordDEFA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordDEFAU(s) @@ -1976,7 +1805,6 @@ func scanKeywordDEFAU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordDEFAUL(s) @@ -1990,7 +1818,6 @@ func scanKeywordDEFAUL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordDEFAULT(s) @@ -2008,7 +1835,6 @@ func scanKeywordDEFE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordDEFER(s) @@ -2022,7 +1848,6 @@ func scanKeywordDEFER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordDEFERR(s) @@ -2036,11 +1861,9 @@ func scanKeywordDEFERR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDEFERRA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordDEFERRE(s) @@ -2054,7 +1877,6 @@ func scanKeywordDEFERRA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordDEFERRAB(s) @@ -2068,7 +1890,6 @@ func scanKeywordDEFERRAB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordDEFERRABL(s) @@ -2082,7 +1903,6 @@ func scanKeywordDEFERRABL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordDEFERRABLE(s) @@ -2100,7 +1920,6 @@ func scanKeywordDEFERRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordDEFERRED(s) @@ -2118,7 +1937,6 @@ func scanKeywordDEL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordDELE(s) @@ -2132,7 +1950,6 @@ func scanKeywordDELE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordDELET(s) @@ -2146,7 +1963,6 @@ func scanKeywordDELET(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordDELETE(s) @@ -2164,7 +1980,6 @@ func scanKeywordDES(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordDESC(s) @@ -2182,7 +1997,6 @@ func scanKeywordDET(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordDETA(s) @@ -2196,7 +2010,6 @@ func scanKeywordDETA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordDETAC(s) @@ -2210,7 +2023,6 @@ func scanKeywordDETAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordDETACH(s) @@ -2228,7 +2040,6 @@ func scanKeywordDI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordDIS(s) @@ -2242,7 +2053,6 @@ func scanKeywordDIS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordDIST(s) @@ -2256,7 +2066,6 @@ func scanKeywordDIST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordDISTI(s) @@ -2270,7 +2079,6 @@ func scanKeywordDISTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordDISTIN(s) @@ -2284,7 +2092,6 @@ func scanKeywordDISTIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordDISTINC(s) @@ -2298,7 +2105,6 @@ func scanKeywordDISTINC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordDISTINCT(s) @@ -2320,7 +2126,6 @@ func scanKeywordDR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordDRO(s) @@ -2334,7 +2139,6 @@ func scanKeywordDRO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordDROP(s) @@ -2352,23 +2156,18 @@ func scanKeywordE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordEA(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordEL(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordEN(s) - case 'S', 's': s.ConsumeRune() return scanKeywordES(s) - case 'X', 'x': s.ConsumeRune() return scanKeywordEX(s) @@ -2382,7 +2181,6 @@ func scanKeywordEA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordEAC(s) @@ -2396,7 +2194,6 @@ func scanKeywordEAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordEACH(s) @@ -2414,7 +2211,6 @@ func scanKeywordEL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordELS(s) @@ -2428,7 +2224,6 @@ func scanKeywordELS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordELSE(s) @@ -2446,7 +2241,6 @@ func scanKeywordEN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordEND(s) @@ -2464,7 +2258,6 @@ func scanKeywordES(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordESC(s) @@ -2478,7 +2271,6 @@ func scanKeywordESC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordESCA(s) @@ -2492,7 +2284,6 @@ func scanKeywordESCA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordESCAP(s) @@ -2506,7 +2297,6 @@ func scanKeywordESCAP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordESCAPE(s) @@ -2524,15 +2314,12 @@ func scanKeywordEX(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordEXC(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordEXI(s) - case 'P', 'p': s.ConsumeRune() return scanKeywordEXP(s) @@ -2546,11 +2333,9 @@ func scanKeywordEXC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordEXCE(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordEXCL(s) @@ -2564,7 +2349,6 @@ func scanKeywordEXCE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordEXCEP(s) @@ -2578,7 +2362,6 @@ func scanKeywordEXCEP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordEXCEPT(s) @@ -2596,7 +2379,6 @@ func scanKeywordEXCL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordEXCLU(s) @@ -2610,11 +2392,9 @@ func scanKeywordEXCLU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordEXCLUD(s) - case 'S', 's': s.ConsumeRune() return scanKeywordEXCLUS(s) @@ -2628,7 +2408,6 @@ func scanKeywordEXCLUD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordEXCLUDE(s) @@ -2646,7 +2425,6 @@ func scanKeywordEXCLUS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordEXCLUSI(s) @@ -2660,7 +2438,6 @@ func scanKeywordEXCLUSI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'V', 'v': s.ConsumeRune() return scanKeywordEXCLUSIV(s) @@ -2674,7 +2451,6 @@ func scanKeywordEXCLUSIV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordEXCLUSIVE(s) @@ -2692,7 +2468,6 @@ func scanKeywordEXI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordEXIS(s) @@ -2706,7 +2481,6 @@ func scanKeywordEXIS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordEXIST(s) @@ -2720,7 +2494,6 @@ func scanKeywordEXIST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordEXISTS(s) @@ -2738,7 +2511,6 @@ func scanKeywordEXP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordEXPL(s) @@ -2752,7 +2524,6 @@ func scanKeywordEXPL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordEXPLA(s) @@ -2766,7 +2537,6 @@ func scanKeywordEXPLA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordEXPLAI(s) @@ -2780,7 +2550,6 @@ func scanKeywordEXPLAI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordEXPLAIN(s) @@ -2798,23 +2567,18 @@ func scanKeywordF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordFA(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordFI(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordFO(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordFR(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordFU(s) @@ -2828,7 +2592,6 @@ func scanKeywordFA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordFAI(s) @@ -2842,7 +2605,6 @@ func scanKeywordFAI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFAIL(s) @@ -2860,11 +2622,9 @@ func scanKeywordFI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFIL(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordFIR(s) @@ -2878,7 +2638,6 @@ func scanKeywordFIL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordFILT(s) @@ -2892,7 +2651,6 @@ func scanKeywordFILT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordFILTE(s) @@ -2906,7 +2664,6 @@ func scanKeywordFILTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordFILTER(s) @@ -2924,7 +2681,6 @@ func scanKeywordFIR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordFIRS(s) @@ -2938,7 +2694,6 @@ func scanKeywordFIRS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordFIRST(s) @@ -2956,11 +2711,9 @@ func scanKeywordFO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFOL(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordFOR(s) @@ -2974,7 +2727,6 @@ func scanKeywordFOL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFOLL(s) @@ -2988,7 +2740,6 @@ func scanKeywordFOLL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordFOLLO(s) @@ -3002,7 +2753,6 @@ func scanKeywordFOLLO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'W', 'w': s.ConsumeRune() return scanKeywordFOLLOW(s) @@ -3016,7 +2766,6 @@ func scanKeywordFOLLOW(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordFOLLOWI(s) @@ -3030,7 +2779,6 @@ func scanKeywordFOLLOWI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordFOLLOWIN(s) @@ -3044,7 +2792,6 @@ func scanKeywordFOLLOWIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordFOLLOWING(s) @@ -3062,7 +2809,6 @@ func scanKeywordFOR(s RuneScanner) (token.Type, bool) { return token.KeywordFor, true } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordFORE(s) @@ -3076,7 +2822,6 @@ func scanKeywordFORE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordFOREI(s) @@ -3090,7 +2835,6 @@ func scanKeywordFOREI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordFOREIG(s) @@ -3104,7 +2848,6 @@ func scanKeywordFOREIG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordFOREIGN(s) @@ -3122,7 +2865,6 @@ func scanKeywordFR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordFRO(s) @@ -3136,7 +2878,6 @@ func scanKeywordFRO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordFROM(s) @@ -3154,7 +2895,6 @@ func scanKeywordFU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFUL(s) @@ -3168,7 +2908,6 @@ func scanKeywordFUL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordFULL(s) @@ -3186,15 +2925,12 @@ func scanKeywordG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordGE(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordGL(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordGR(s) @@ -3208,7 +2944,6 @@ func scanKeywordGE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordGEN(s) @@ -3222,7 +2957,6 @@ func scanKeywordGEN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordGENE(s) @@ -3236,7 +2970,6 @@ func scanKeywordGENE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordGENER(s) @@ -3250,7 +2983,6 @@ func scanKeywordGENER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordGENERA(s) @@ -3264,7 +2996,6 @@ func scanKeywordGENERA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordGENERAT(s) @@ -3278,7 +3009,6 @@ func scanKeywordGENERAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordGENERATE(s) @@ -3292,7 +3022,6 @@ func scanKeywordGENERATE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordGENERATED(s) @@ -3310,7 +3039,6 @@ func scanKeywordGL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordGLO(s) @@ -3324,7 +3052,6 @@ func scanKeywordGLO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordGLOB(s) @@ -3342,7 +3069,6 @@ func scanKeywordGR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordGRO(s) @@ -3356,7 +3082,6 @@ func scanKeywordGRO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordGROU(s) @@ -3370,7 +3095,6 @@ func scanKeywordGROU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordGROUP(s) @@ -3384,7 +3108,6 @@ func scanKeywordGROUP(s RuneScanner) (token.Type, bool) { return token.KeywordGroup, true } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordGROUPS(s) @@ -3402,7 +3125,6 @@ func scanKeywordH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordHA(s) @@ -3416,7 +3138,6 @@ func scanKeywordHA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'V', 'v': s.ConsumeRune() return scanKeywordHAV(s) @@ -3430,7 +3151,6 @@ func scanKeywordHAV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordHAVI(s) @@ -3444,7 +3164,6 @@ func scanKeywordHAVI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordHAVIN(s) @@ -3458,7 +3177,6 @@ func scanKeywordHAVIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordHAVING(s) @@ -3476,23 +3194,18 @@ func scanKeywordI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordIF(s) - case 'G', 'g': s.ConsumeRune() return scanKeywordIG(s) - case 'M', 'm': s.ConsumeRune() return scanKeywordIM(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordIN(s) - case 'S', 's': s.ConsumeRune() return scanKeywordIS(s) @@ -3510,7 +3223,6 @@ func scanKeywordIG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordIGN(s) @@ -3524,7 +3236,6 @@ func scanKeywordIGN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordIGNO(s) @@ -3538,7 +3249,6 @@ func scanKeywordIGNO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordIGNOR(s) @@ -3552,7 +3262,6 @@ func scanKeywordIGNOR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordIGNORE(s) @@ -3570,7 +3279,6 @@ func scanKeywordIM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordIMM(s) @@ -3584,7 +3292,6 @@ func scanKeywordIMM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordIMME(s) @@ -3598,7 +3305,6 @@ func scanKeywordIMME(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordIMMED(s) @@ -3612,7 +3318,6 @@ func scanKeywordIMMED(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordIMMEDI(s) @@ -3626,7 +3331,6 @@ func scanKeywordIMMEDI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordIMMEDIA(s) @@ -3640,7 +3344,6 @@ func scanKeywordIMMEDIA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordIMMEDIAT(s) @@ -3654,7 +3357,6 @@ func scanKeywordIMMEDIAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordIMMEDIATE(s) @@ -3672,23 +3374,18 @@ func scanKeywordIN(s RuneScanner) (token.Type, bool) { return token.KeywordIn, true } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordIND(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordINI(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordINN(s) - case 'S', 's': s.ConsumeRune() return scanKeywordINS(s) - case 'T', 't': s.ConsumeRune() return scanKeywordINT(s) @@ -3702,7 +3399,6 @@ func scanKeywordIND(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINDE(s) @@ -3716,7 +3412,6 @@ func scanKeywordINDE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'X', 'x': s.ConsumeRune() return scanKeywordINDEX(s) @@ -3730,7 +3425,6 @@ func scanKeywordINDEX(s RuneScanner) (token.Type, bool) { return token.KeywordIndex, true } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINDEXE(s) @@ -3744,7 +3438,6 @@ func scanKeywordINDEXE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordINDEXED(s) @@ -3762,7 +3455,6 @@ func scanKeywordINI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordINIT(s) @@ -3776,7 +3468,6 @@ func scanKeywordINIT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordINITI(s) @@ -3790,7 +3481,6 @@ func scanKeywordINITI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordINITIA(s) @@ -3804,7 +3494,6 @@ func scanKeywordINITIA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordINITIAL(s) @@ -3818,7 +3507,6 @@ func scanKeywordINITIAL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordINITIALL(s) @@ -3832,7 +3520,6 @@ func scanKeywordINITIALL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordINITIALLY(s) @@ -3850,7 +3537,6 @@ func scanKeywordINN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINNE(s) @@ -3864,7 +3550,6 @@ func scanKeywordINNE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordINNER(s) @@ -3882,11 +3567,9 @@ func scanKeywordINS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINSE(s) - case 'T', 't': s.ConsumeRune() return scanKeywordINST(s) @@ -3900,7 +3583,6 @@ func scanKeywordINSE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordINSER(s) @@ -3914,7 +3596,6 @@ func scanKeywordINSER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordINSERT(s) @@ -3932,7 +3613,6 @@ func scanKeywordINST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINSTE(s) @@ -3946,7 +3626,6 @@ func scanKeywordINSTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordINSTEA(s) @@ -3960,7 +3639,6 @@ func scanKeywordINSTEA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordINSTEAD(s) @@ -3978,11 +3656,9 @@ func scanKeywordINT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINTE(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordINTO(s) @@ -3996,7 +3672,6 @@ func scanKeywordINTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordINTER(s) @@ -4010,7 +3685,6 @@ func scanKeywordINTER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordINTERS(s) @@ -4024,7 +3698,6 @@ func scanKeywordINTERS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordINTERSE(s) @@ -4038,7 +3711,6 @@ func scanKeywordINTERSE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordINTERSEC(s) @@ -4052,7 +3724,6 @@ func scanKeywordINTERSEC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordINTERSECT(s) @@ -4074,7 +3745,6 @@ func scanKeywordIS(s RuneScanner) (token.Type, bool) { return token.KeywordIs, true } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordISN(s) @@ -4088,7 +3758,6 @@ func scanKeywordISN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordISNU(s) @@ -4102,7 +3771,6 @@ func scanKeywordISNU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordISNUL(s) @@ -4116,7 +3784,6 @@ func scanKeywordISNUL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordISNULL(s) @@ -4134,7 +3801,6 @@ func scanKeywordJ(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordJO(s) @@ -4148,7 +3814,6 @@ func scanKeywordJO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordJOI(s) @@ -4162,7 +3827,6 @@ func scanKeywordJOI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordJOIN(s) @@ -4180,7 +3844,6 @@ func scanKeywordK(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordKE(s) @@ -4194,7 +3857,6 @@ func scanKeywordKE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordKEY(s) @@ -4212,15 +3874,12 @@ func scanKeywordL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordLA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordLE(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordLI(s) @@ -4234,7 +3893,6 @@ func scanKeywordLA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordLAS(s) @@ -4248,7 +3906,6 @@ func scanKeywordLAS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordLAST(s) @@ -4266,7 +3923,6 @@ func scanKeywordLE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordLEF(s) @@ -4280,7 +3936,6 @@ func scanKeywordLEF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordLEFT(s) @@ -4298,11 +3953,9 @@ func scanKeywordLI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'K', 'k': s.ConsumeRune() return scanKeywordLIK(s) - case 'M', 'm': s.ConsumeRune() return scanKeywordLIM(s) @@ -4316,7 +3969,6 @@ func scanKeywordLIK(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordLIKE(s) @@ -4334,7 +3986,6 @@ func scanKeywordLIM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordLIMI(s) @@ -4348,7 +3999,6 @@ func scanKeywordLIMI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordLIMIT(s) @@ -4366,7 +4016,6 @@ func scanKeywordM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordMA(s) @@ -4380,7 +4029,6 @@ func scanKeywordMA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordMAT(s) @@ -4394,7 +4042,6 @@ func scanKeywordMAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordMATC(s) @@ -4408,7 +4055,6 @@ func scanKeywordMATC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordMATCH(s) @@ -4426,15 +4072,12 @@ func scanKeywordN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordNA(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordNO(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordNU(s) @@ -4448,7 +4091,6 @@ func scanKeywordNA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordNAT(s) @@ -4462,7 +4104,6 @@ func scanKeywordNAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordNATU(s) @@ -4476,7 +4117,6 @@ func scanKeywordNATU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordNATUR(s) @@ -4490,7 +4130,6 @@ func scanKeywordNATUR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordNATURA(s) @@ -4504,7 +4143,6 @@ func scanKeywordNATURA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordNATURAL(s) @@ -4522,7 +4160,6 @@ func scanKeywordNO(s RuneScanner) (token.Type, bool) { return token.KeywordNo, true } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordNOT(s) @@ -4536,11 +4173,9 @@ func scanKeywordNOT(s RuneScanner) (token.Type, bool) { return token.KeywordNot, true } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordNOTH(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordNOTN(s) @@ -4554,7 +4189,6 @@ func scanKeywordNOTH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordNOTHI(s) @@ -4568,7 +4202,6 @@ func scanKeywordNOTHI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordNOTHIN(s) @@ -4582,7 +4215,6 @@ func scanKeywordNOTHIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordNOTHING(s) @@ -4600,7 +4232,6 @@ func scanKeywordNOTN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordNOTNU(s) @@ -4614,7 +4245,6 @@ func scanKeywordNOTNU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordNOTNUL(s) @@ -4628,7 +4258,6 @@ func scanKeywordNOTNUL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordNOTNULL(s) @@ -4646,7 +4275,6 @@ func scanKeywordNU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordNUL(s) @@ -4660,7 +4288,6 @@ func scanKeywordNUL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordNULL(s) @@ -4674,7 +4301,6 @@ func scanKeywordNULL(s RuneScanner) (token.Type, bool) { return token.KeywordNull, true } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordNULLS(s) @@ -4692,27 +4318,21 @@ func scanKeywordO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordOF(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordON(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordOR(s) - case 'T', 't': s.ConsumeRune() return scanKeywordOT(s) - case 'U', 'u': s.ConsumeRune() return scanKeywordOU(s) - case 'V', 'v': s.ConsumeRune() return scanKeywordOV(s) @@ -4726,7 +4346,6 @@ func scanKeywordOF(s RuneScanner) (token.Type, bool) { return token.KeywordOf, true } switch next { - case 'F', 'f': s.ConsumeRune() return scanKeywordOFF(s) @@ -4740,7 +4359,6 @@ func scanKeywordOFF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordOFFS(s) @@ -4754,7 +4372,6 @@ func scanKeywordOFFS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordOFFSE(s) @@ -4768,7 +4385,6 @@ func scanKeywordOFFSE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordOFFSET(s) @@ -4790,7 +4406,6 @@ func scanKeywordOR(s RuneScanner) (token.Type, bool) { return token.KeywordOr, true } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordORD(s) @@ -4804,7 +4419,6 @@ func scanKeywordORD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordORDE(s) @@ -4818,7 +4432,6 @@ func scanKeywordORDE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordORDER(s) @@ -4836,7 +4449,6 @@ func scanKeywordOT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordOTH(s) @@ -4850,7 +4462,6 @@ func scanKeywordOTH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordOTHE(s) @@ -4864,7 +4475,6 @@ func scanKeywordOTHE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordOTHER(s) @@ -4878,7 +4488,6 @@ func scanKeywordOTHER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordOTHERS(s) @@ -4896,7 +4505,6 @@ func scanKeywordOU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordOUT(s) @@ -4910,7 +4518,6 @@ func scanKeywordOUT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordOUTE(s) @@ -4924,7 +4531,6 @@ func scanKeywordOUTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordOUTER(s) @@ -4942,7 +4548,6 @@ func scanKeywordOV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordOVE(s) @@ -4956,7 +4561,6 @@ func scanKeywordOVE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordOVER(s) @@ -4974,15 +4578,12 @@ func scanKeywordP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordPA(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordPL(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordPR(s) @@ -4996,7 +4597,6 @@ func scanKeywordPA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordPAR(s) @@ -5010,7 +4610,6 @@ func scanKeywordPAR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordPART(s) @@ -5024,7 +4623,6 @@ func scanKeywordPART(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordPARTI(s) @@ -5038,7 +4636,6 @@ func scanKeywordPARTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordPARTIT(s) @@ -5052,7 +4649,6 @@ func scanKeywordPARTIT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordPARTITI(s) @@ -5066,7 +4662,6 @@ func scanKeywordPARTITI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordPARTITIO(s) @@ -5080,7 +4675,6 @@ func scanKeywordPARTITIO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordPARTITION(s) @@ -5098,7 +4692,6 @@ func scanKeywordPL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordPLA(s) @@ -5112,7 +4705,6 @@ func scanKeywordPLA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordPLAN(s) @@ -5130,15 +4722,12 @@ func scanKeywordPR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordPRA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordPRE(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordPRI(s) @@ -5152,7 +4741,6 @@ func scanKeywordPRA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordPRAG(s) @@ -5166,7 +4754,6 @@ func scanKeywordPRAG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordPRAGM(s) @@ -5180,7 +4767,6 @@ func scanKeywordPRAGM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordPRAGMA(s) @@ -5198,7 +4784,6 @@ func scanKeywordPRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordPREC(s) @@ -5212,7 +4797,6 @@ func scanKeywordPREC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordPRECE(s) @@ -5226,7 +4810,6 @@ func scanKeywordPRECE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordPRECED(s) @@ -5240,7 +4823,6 @@ func scanKeywordPRECED(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordPRECEDI(s) @@ -5254,7 +4836,6 @@ func scanKeywordPRECEDI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordPRECEDIN(s) @@ -5268,7 +4849,6 @@ func scanKeywordPRECEDIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordPRECEDING(s) @@ -5286,7 +4866,6 @@ func scanKeywordPRI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordPRIM(s) @@ -5300,7 +4879,6 @@ func scanKeywordPRIM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordPRIMA(s) @@ -5314,7 +4892,6 @@ func scanKeywordPRIMA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordPRIMAR(s) @@ -5328,7 +4905,6 @@ func scanKeywordPRIMAR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordPRIMARY(s) @@ -5346,7 +4922,6 @@ func scanKeywordQ(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordQU(s) @@ -5360,7 +4935,6 @@ func scanKeywordQU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordQUE(s) @@ -5374,7 +4948,6 @@ func scanKeywordQUE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordQUER(s) @@ -5388,7 +4961,6 @@ func scanKeywordQUER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordQUERY(s) @@ -5406,19 +4978,15 @@ func scanKeywordR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordRA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordRE(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordRI(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordRO(s) @@ -5432,11 +5000,9 @@ func scanKeywordRA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordRAI(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordRAN(s) @@ -5450,7 +5016,6 @@ func scanKeywordRAI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordRAIS(s) @@ -5464,7 +5029,6 @@ func scanKeywordRAIS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRAISE(s) @@ -5482,7 +5046,6 @@ func scanKeywordRAN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordRANG(s) @@ -5496,7 +5059,6 @@ func scanKeywordRANG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRANGE(s) @@ -5514,35 +5076,27 @@ func scanKeywordRE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordREC(s) - case 'F', 'f': s.ConsumeRune() return scanKeywordREF(s) - case 'G', 'g': s.ConsumeRune() return scanKeywordREG(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordREI(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordREL(s) - case 'N', 'n': s.ConsumeRune() return scanKeywordREN(s) - case 'P', 'p': s.ConsumeRune() return scanKeywordREP(s) - case 'S', 's': s.ConsumeRune() return scanKeywordRES(s) @@ -5556,7 +5110,6 @@ func scanKeywordREC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordRECU(s) @@ -5570,7 +5123,6 @@ func scanKeywordRECU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordRECUR(s) @@ -5584,7 +5136,6 @@ func scanKeywordRECUR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordRECURS(s) @@ -5598,7 +5149,6 @@ func scanKeywordRECURS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordRECURSI(s) @@ -5612,7 +5162,6 @@ func scanKeywordRECURSI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'V', 'v': s.ConsumeRune() return scanKeywordRECURSIV(s) @@ -5626,7 +5175,6 @@ func scanKeywordRECURSIV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRECURSIVE(s) @@ -5644,7 +5192,6 @@ func scanKeywordREF(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREFE(s) @@ -5658,7 +5205,6 @@ func scanKeywordREFE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordREFER(s) @@ -5672,7 +5218,6 @@ func scanKeywordREFER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREFERE(s) @@ -5686,7 +5231,6 @@ func scanKeywordREFERE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordREFEREN(s) @@ -5700,7 +5244,6 @@ func scanKeywordREFEREN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordREFERENC(s) @@ -5714,7 +5257,6 @@ func scanKeywordREFERENC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREFERENCE(s) @@ -5728,7 +5270,6 @@ func scanKeywordREFERENCE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordREFERENCES(s) @@ -5746,7 +5287,6 @@ func scanKeywordREG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREGE(s) @@ -5760,7 +5300,6 @@ func scanKeywordREGE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'X', 'x': s.ConsumeRune() return scanKeywordREGEX(s) @@ -5774,7 +5313,6 @@ func scanKeywordREGEX(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordREGEXP(s) @@ -5792,7 +5330,6 @@ func scanKeywordREI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordREIN(s) @@ -5806,7 +5343,6 @@ func scanKeywordREIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordREIND(s) @@ -5820,7 +5356,6 @@ func scanKeywordREIND(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREINDE(s) @@ -5834,7 +5369,6 @@ func scanKeywordREINDE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'X', 'x': s.ConsumeRune() return scanKeywordREINDEX(s) @@ -5852,7 +5386,6 @@ func scanKeywordREL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRELE(s) @@ -5866,7 +5399,6 @@ func scanKeywordRELE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordRELEA(s) @@ -5880,7 +5412,6 @@ func scanKeywordRELEA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordRELEAS(s) @@ -5894,7 +5425,6 @@ func scanKeywordRELEAS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRELEASE(s) @@ -5912,7 +5442,6 @@ func scanKeywordREN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordRENA(s) @@ -5926,7 +5455,6 @@ func scanKeywordRENA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordRENAM(s) @@ -5940,7 +5468,6 @@ func scanKeywordRENAM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordRENAME(s) @@ -5958,7 +5485,6 @@ func scanKeywordREP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordREPL(s) @@ -5972,7 +5498,6 @@ func scanKeywordREPL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordREPLA(s) @@ -5986,7 +5511,6 @@ func scanKeywordREPLA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordREPLAC(s) @@ -6000,7 +5524,6 @@ func scanKeywordREPLAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordREPLACE(s) @@ -6018,7 +5541,6 @@ func scanKeywordRES(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordREST(s) @@ -6032,7 +5554,6 @@ func scanKeywordREST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordRESTR(s) @@ -6046,7 +5567,6 @@ func scanKeywordRESTR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordRESTRI(s) @@ -6060,7 +5580,6 @@ func scanKeywordRESTRI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordRESTRIC(s) @@ -6074,7 +5593,6 @@ func scanKeywordRESTRIC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordRESTRICT(s) @@ -6092,7 +5610,6 @@ func scanKeywordRI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordRIG(s) @@ -6106,7 +5623,6 @@ func scanKeywordRIG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordRIGH(s) @@ -6120,7 +5636,6 @@ func scanKeywordRIGH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordRIGHT(s) @@ -6138,11 +5653,9 @@ func scanKeywordRO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordROL(s) - case 'W', 'w': s.ConsumeRune() return scanKeywordROW(s) @@ -6156,7 +5669,6 @@ func scanKeywordROL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordROLL(s) @@ -6170,7 +5682,6 @@ func scanKeywordROLL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordROLLB(s) @@ -6184,7 +5695,6 @@ func scanKeywordROLLB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordROLLBA(s) @@ -6198,7 +5708,6 @@ func scanKeywordROLLBA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordROLLBAC(s) @@ -6212,7 +5721,6 @@ func scanKeywordROLLBAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'K', 'k': s.ConsumeRune() return scanKeywordROLLBACK(s) @@ -6230,7 +5738,6 @@ func scanKeywordROW(s RuneScanner) (token.Type, bool) { return token.KeywordRow, true } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordROWS(s) @@ -6248,15 +5755,12 @@ func scanKeywordS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordSA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordSE(s) - case 'T', 't': s.ConsumeRune() return scanKeywordST(s) @@ -6270,7 +5774,6 @@ func scanKeywordSA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'V', 'v': s.ConsumeRune() return scanKeywordSAV(s) @@ -6284,7 +5787,6 @@ func scanKeywordSAV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordSAVE(s) @@ -6298,7 +5800,6 @@ func scanKeywordSAVE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordSAVEP(s) @@ -6312,7 +5813,6 @@ func scanKeywordSAVEP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordSAVEPO(s) @@ -6326,7 +5826,6 @@ func scanKeywordSAVEPO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordSAVEPOI(s) @@ -6340,7 +5839,6 @@ func scanKeywordSAVEPOI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordSAVEPOIN(s) @@ -6354,7 +5852,6 @@ func scanKeywordSAVEPOIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordSAVEPOINT(s) @@ -6372,11 +5869,9 @@ func scanKeywordSE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordSEL(s) - case 'T', 't': s.ConsumeRune() return scanKeywordSET(s) @@ -6390,7 +5885,6 @@ func scanKeywordSEL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordSELE(s) @@ -6404,7 +5898,6 @@ func scanKeywordSELE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordSELEC(s) @@ -6418,7 +5911,6 @@ func scanKeywordSELEC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordSELECT(s) @@ -6440,7 +5932,6 @@ func scanKeywordST(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordSTO(s) @@ -6454,7 +5945,6 @@ func scanKeywordSTO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordSTOR(s) @@ -6468,7 +5958,6 @@ func scanKeywordSTOR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordSTORE(s) @@ -6482,7 +5971,6 @@ func scanKeywordSTORE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordSTORED(s) @@ -6500,27 +5988,21 @@ func scanKeywordT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordTA(s) - case 'E', 'e': s.ConsumeRune() return scanKeywordTE(s) - case 'H', 'h': s.ConsumeRune() return scanKeywordTH(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordTI(s) - case 'O', 'o': s.ConsumeRune() return scanKeywordTO(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordTR(s) @@ -6534,7 +6016,6 @@ func scanKeywordTA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordTAB(s) @@ -6548,7 +6029,6 @@ func scanKeywordTAB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordTABL(s) @@ -6562,7 +6042,6 @@ func scanKeywordTABL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordTABLE(s) @@ -6580,7 +6059,6 @@ func scanKeywordTE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordTEM(s) @@ -6594,7 +6072,6 @@ func scanKeywordTEM(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'P', 'p': s.ConsumeRune() return scanKeywordTEMP(s) @@ -6608,7 +6085,6 @@ func scanKeywordTEMP(s RuneScanner) (token.Type, bool) { return token.KeywordTemp, true } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordTEMPO(s) @@ -6622,7 +6098,6 @@ func scanKeywordTEMPO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordTEMPOR(s) @@ -6636,7 +6111,6 @@ func scanKeywordTEMPOR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordTEMPORA(s) @@ -6650,7 +6124,6 @@ func scanKeywordTEMPORA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordTEMPORAR(s) @@ -6664,7 +6137,6 @@ func scanKeywordTEMPORAR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'Y', 'y': s.ConsumeRune() return scanKeywordTEMPORARY(s) @@ -6682,7 +6154,6 @@ func scanKeywordTH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordTHE(s) @@ -6696,7 +6167,6 @@ func scanKeywordTHE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordTHEN(s) @@ -6714,7 +6184,6 @@ func scanKeywordTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordTIE(s) @@ -6728,7 +6197,6 @@ func scanKeywordTIE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordTIES(s) @@ -6750,11 +6218,9 @@ func scanKeywordTR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordTRA(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordTRI(s) @@ -6768,7 +6234,6 @@ func scanKeywordTRA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordTRAN(s) @@ -6782,7 +6247,6 @@ func scanKeywordTRAN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordTRANS(s) @@ -6796,7 +6260,6 @@ func scanKeywordTRANS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordTRANSA(s) @@ -6810,7 +6273,6 @@ func scanKeywordTRANSA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordTRANSAC(s) @@ -6824,7 +6286,6 @@ func scanKeywordTRANSAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordTRANSACT(s) @@ -6838,7 +6299,6 @@ func scanKeywordTRANSACT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordTRANSACTI(s) @@ -6852,7 +6312,6 @@ func scanKeywordTRANSACTI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordTRANSACTIO(s) @@ -6866,7 +6325,6 @@ func scanKeywordTRANSACTIO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordTRANSACTION(s) @@ -6884,7 +6342,6 @@ func scanKeywordTRI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordTRIG(s) @@ -6898,7 +6355,6 @@ func scanKeywordTRIG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordTRIGG(s) @@ -6912,7 +6368,6 @@ func scanKeywordTRIGG(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordTRIGGE(s) @@ -6926,7 +6381,6 @@ func scanKeywordTRIGGE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'R', 'r': s.ConsumeRune() return scanKeywordTRIGGER(s) @@ -6944,15 +6398,12 @@ func scanKeywordU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordUN(s) - case 'P', 'p': s.ConsumeRune() return scanKeywordUP(s) - case 'S', 's': s.ConsumeRune() return scanKeywordUS(s) @@ -6966,11 +6417,9 @@ func scanKeywordUN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'B', 'b': s.ConsumeRune() return scanKeywordUNB(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordUNI(s) @@ -6984,7 +6433,6 @@ func scanKeywordUNB(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordUNBO(s) @@ -6998,7 +6446,6 @@ func scanKeywordUNBO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordUNBOU(s) @@ -7012,7 +6459,6 @@ func scanKeywordUNBOU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordUNBOUN(s) @@ -7026,7 +6472,6 @@ func scanKeywordUNBOUN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordUNBOUND(s) @@ -7040,7 +6485,6 @@ func scanKeywordUNBOUND(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordUNBOUNDE(s) @@ -7054,7 +6498,6 @@ func scanKeywordUNBOUNDE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordUNBOUNDED(s) @@ -7072,11 +6515,9 @@ func scanKeywordUNI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordUNIO(s) - case 'Q', 'q': s.ConsumeRune() return scanKeywordUNIQ(s) @@ -7090,7 +6531,6 @@ func scanKeywordUNIO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordUNION(s) @@ -7108,7 +6548,6 @@ func scanKeywordUNIQ(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordUNIQU(s) @@ -7122,7 +6561,6 @@ func scanKeywordUNIQU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordUNIQUE(s) @@ -7140,7 +6578,6 @@ func scanKeywordUP(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordUPD(s) @@ -7154,7 +6591,6 @@ func scanKeywordUPD(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordUPDA(s) @@ -7168,7 +6604,6 @@ func scanKeywordUPDA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordUPDAT(s) @@ -7182,7 +6617,6 @@ func scanKeywordUPDAT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordUPDATE(s) @@ -7200,7 +6634,6 @@ func scanKeywordUS(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'I', 'i': s.ConsumeRune() return scanKeywordUSI(s) @@ -7214,7 +6647,6 @@ func scanKeywordUSI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordUSIN(s) @@ -7228,7 +6660,6 @@ func scanKeywordUSIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'G', 'g': s.ConsumeRune() return scanKeywordUSING(s) @@ -7246,11 +6677,9 @@ func scanKeywordV(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordVA(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordVI(s) @@ -7264,11 +6693,9 @@ func scanKeywordVA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'C', 'c': s.ConsumeRune() return scanKeywordVAC(s) - case 'L', 'l': s.ConsumeRune() return scanKeywordVAL(s) @@ -7282,7 +6709,6 @@ func scanKeywordVAC(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordVACU(s) @@ -7296,7 +6722,6 @@ func scanKeywordVACU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordVACUU(s) @@ -7310,7 +6735,6 @@ func scanKeywordVACUU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'M', 'm': s.ConsumeRune() return scanKeywordVACUUM(s) @@ -7328,7 +6752,6 @@ func scanKeywordVAL(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordVALU(s) @@ -7342,7 +6765,6 @@ func scanKeywordVALU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordVALUE(s) @@ -7356,7 +6778,6 @@ func scanKeywordVALUE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'S', 's': s.ConsumeRune() return scanKeywordVALUES(s) @@ -7374,11 +6795,9 @@ func scanKeywordVI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordVIE(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordVIR(s) @@ -7392,7 +6811,6 @@ func scanKeywordVIE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'W', 'w': s.ConsumeRune() return scanKeywordVIEW(s) @@ -7410,7 +6828,6 @@ func scanKeywordVIR(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordVIRT(s) @@ -7424,7 +6841,6 @@ func scanKeywordVIRT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordVIRTU(s) @@ -7438,7 +6854,6 @@ func scanKeywordVIRTU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'A', 'a': s.ConsumeRune() return scanKeywordVIRTUA(s) @@ -7452,7 +6867,6 @@ func scanKeywordVIRTUA(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'L', 'l': s.ConsumeRune() return scanKeywordVIRTUAL(s) @@ -7470,11 +6884,9 @@ func scanKeywordW(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordWH(s) - case 'I', 'i': s.ConsumeRune() return scanKeywordWI(s) @@ -7488,7 +6900,6 @@ func scanKeywordWH(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordWHE(s) @@ -7502,11 +6913,9 @@ func scanKeywordWHE(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordWHEN(s) - case 'R', 'r': s.ConsumeRune() return scanKeywordWHER(s) @@ -7524,7 +6933,6 @@ func scanKeywordWHER(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'E', 'e': s.ConsumeRune() return scanKeywordWHERE(s) @@ -7542,11 +6950,9 @@ func scanKeywordWI(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'N', 'n': s.ConsumeRune() return scanKeywordWIN(s) - case 'T', 't': s.ConsumeRune() return scanKeywordWIT(s) @@ -7560,7 +6966,6 @@ func scanKeywordWIN(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'D', 'd': s.ConsumeRune() return scanKeywordWIND(s) @@ -7574,7 +6979,6 @@ func scanKeywordWIND(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordWINDO(s) @@ -7588,7 +6992,6 @@ func scanKeywordWINDO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'W', 'w': s.ConsumeRune() return scanKeywordWINDOW(s) @@ -7606,7 +7009,6 @@ func scanKeywordWIT(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'H', 'h': s.ConsumeRune() return scanKeywordWITH(s) @@ -7620,7 +7022,6 @@ func scanKeywordWITH(s RuneScanner) (token.Type, bool) { return token.KeywordWith, true } switch next { - case 'O', 'o': s.ConsumeRune() return scanKeywordWITHO(s) @@ -7634,7 +7035,6 @@ func scanKeywordWITHO(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'U', 'u': s.ConsumeRune() return scanKeywordWITHOU(s) @@ -7648,7 +7048,6 @@ func scanKeywordWITHOU(s RuneScanner) (token.Type, bool) { return token.Unknown, false } switch next { - case 'T', 't': s.ConsumeRune() return scanKeywordWITHOUT(s) @@ -7658,4 +7057,4 @@ func scanKeywordWITHOU(s RuneScanner) (token.Type, bool) { func scanKeywordWITHOUT(s RuneScanner) (token.Type, bool) { return token.KeywordWithout, true -} +} \ No newline at end of file diff --git a/internal/parser/scanner/token/type_string.go b/internal/parser/scanner/token/type_string.go index 8fc862f6..6f044e82 100644 --- a/internal/parser/scanner/token/type_string.go +++ b/internal/parser/scanner/token/type_string.go @@ -165,7 +165,7 @@ func _() { _ = x[Delimiter-154] } -const _Type_name = "UnknownErrorEOFStatementSeparatorKeywordAbortKeywordActionKeywordAddKeywordAfterKeywordAllKeywordAlterKeywordAlwaysKeywordAnalyzeKeywordAndKeywordAsKeywordAscKeywordAttachKeywordAutoincrementKeywordBeforeKeywordBeginKeywordBetweenKeywordByKeywordCascadeKeywordCaseKeywordCastKeywordCheckKeywordCollateKeywordColumnKeywordCommitKeywordConflictKeywordConstraintKeywordCreateKeywordCrossKeywordCurrentKeywordCurrentDateKeywordCurrentTimeKeywordCurrentTimestampKeywordDatabaseKeywordDefaultKeywordDeferrableKeywordDeferredKeywordDeleteKeywordDescKeywordDetachKeywordDistinctKeywordDoKeywordDropKeywordEachKeywordElseKeywordEndKeywordEscapeKeywordExceptKeywordExcludeKeywordExclusiveKeywordExistsKeywordExplainKeywordFailKeywordFilterKeywordFirstKeywordFollowingKeywordForKeywordForeignKeywordFromKeywordFullKeywordGeneratedKeywordGlobKeywordGroupKeywordGroupsKeywordHavingKeywordIfKeywordIgnoreKeywordImmediateKeywordInKeywordIndexKeywordIndexedKeywordInitiallyKeywordInnerKeywordInsertKeywordInsteadKeywordIntersectKeywordIntoKeywordIsKeywordIsnullKeywordJoinKeywordKeyKeywordLastKeywordLeftKeywordLikeKeywordLimitKeywordMatchKeywordNaturalKeywordNoKeywordNotKeywordNothingKeywordNotnullKeywordNullKeywordNullsKeywordOfKeywordOffsetKeywordOnKeywordOrKeywordOrderKeywordOthersKeywordOuterKeywordOverKeywordPartitionKeywordPlanKeywordPragmaKeywordPrecedingKeywordPrimaryKeywordQueryKeywordRaiseKeywordRangeKeywordRecursiveKeywordReferencesKeywordRegexpKeywordReindexKeywordReleaseKeywordRenameKeywordReplaceKeywordRestrictKeywordRightKeywordRollbackKeywordRowKeywordRowsKeywordSavepointKeywordSelectKeywordSetKeywordStoredKeywordTableKeywordTempKeywordTemporaryKeywordThenKeywordTiesKeywordToKeywordTransactionKeywordTriggerKeywordUnboundedKeywordUnionKeywordUniqueKeywordUpdateKeywordUsingKeywordVacuumKeywordValuesKeywordViewKeywordVirtualKeywordWhenKeywordWhereKeywordWindowKeywordWithKeywordWithoutLiteralLiteralNumericUnaryOperatorBinaryOperatorDelimiter" +const _Type_name = "UnknownErrorEOFStatementSeparatorKeywordAbortKeywordActionKeywordAddKeywordAfterKeywordAllKeywordAlterKeywordAlwaysKeywordAnalyzeKeywordAndKeywordAsKeywordAscKeywordAttachKeywordAutoincrementKeywordBeforeKeywordBeginKeywordBetweenKeywordByKeywordCascadeKeywordCaseKeywordCastKeywordCheckKeywordCollateKeywordColumnKeywordCommitKeywordConflictKeywordConstraintKeywordCreateKeywordCrossKeywordCurrentKeywordCurrentDateKeywordCurrentTimeKeywordCurrentTimestampKeywordDatabaseKeywordDefaultKeywordDeferrableKeywordDeferredKeywordDeleteKeywordDescKeywordDetachKeywordDistinctKeywordDoKeywordDropKeywordEachKeywordElseKeywordEndKeywordEscapeKeywordExceptKeywordExcludeKeywordExclusiveKeywordExistsKeywordExplainKeywordFailKeywordFilterKeywordFirstKeywordFollowingKeywordForKeywordForeignKeywordFromKeywordFullKeywordGeneratedKeywordGlobKeywordGroupKeywordGroupsKeywordHavingKeywordIfKeywordIgnoreKeywordImmediateKeywordInKeywordIndexKeywordIndexedKeywordInitiallyKeywordInnerKeywordInsertKeywordInsteadKeywordIntersectKeywordIntoKeywordIsKeywordIsnullKeywordJoinKeywordKeyKeywordLastKeywordLeftKeywordLikeKeywordLimitKeywordMatchKeywordNaturalKeywordNoKeywordNotKeywordNothingKeywordNotnullKeywordNullKeywordNullsKeywordOfKeywordOffsetKeywordOnKeywordOrKeywordOrderKeywordOthersKeywordOuterKeywordOverKeywordPartitionKeywordPlanKeywordPragmaKeywordPrecedingKeywordPrimaryKeywordQueryKeywordRaiseKeywordRangeKeywordRecursiveKeywordReferencesKeywordRegexpKeywordReIndexKeywordReleaseKeywordRenameKeywordReplaceKeywordRestrictKeywordRightKeywordRollbackKeywordRowKeywordRowsKeywordSavepointKeywordSelectKeywordSetKeywordStoredKeywordTableKeywordTempKeywordTemporaryKeywordThenKeywordTiesKeywordToKeywordTransactionKeywordTriggerKeywordUnboundedKeywordUnionKeywordUniqueKeywordUpdateKeywordUsingKeywordVacuumKeywordValuesKeywordViewKeywordVirtualKeywordWhenKeywordWhereKeywordWindowKeywordWithKeywordWithoutLiteralLiteralNumericUnaryOperatorBinaryOperatorDelimiter" var _Type_index = [...]uint16{0, 7, 12, 15, 33, 45, 58, 68, 80, 90, 102, 115, 129, 139, 148, 158, 171, 191, 204, 216, 230, 239, 253, 264, 275, 287, 301, 314, 327, 342, 359, 372, 384, 398, 416, 434, 457, 472, 486, 503, 518, 531, 542, 555, 570, 579, 590, 601, 612, 622, 635, 648, 662, 678, 691, 705, 716, 729, 741, 757, 767, 781, 792, 803, 819, 830, 842, 855, 868, 877, 890, 906, 915, 927, 941, 957, 969, 982, 996, 1012, 1023, 1032, 1045, 1056, 1066, 1077, 1088, 1099, 1111, 1123, 1137, 1146, 1156, 1170, 1184, 1195, 1207, 1216, 1229, 1238, 1247, 1259, 1272, 1284, 1295, 1311, 1322, 1335, 1351, 1365, 1377, 1389, 1401, 1417, 1434, 1447, 1461, 1475, 1488, 1502, 1517, 1529, 1544, 1554, 1565, 1581, 1594, 1604, 1617, 1629, 1640, 1656, 1667, 1678, 1687, 1705, 1719, 1735, 1747, 1760, 1773, 1785, 1798, 1811, 1822, 1836, 1847, 1859, 1872, 1883, 1897, 1904, 1918, 1931, 1945, 1954} diff --git a/internal/raft/append_entries.go b/internal/raft/append_entries.go new file mode 100644 index 00000000..2d09b441 --- /dev/null +++ b/internal/raft/append_entries.go @@ -0,0 +1,74 @@ +package raft + +import ( + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// AppendEntriesResponse function is called on a request from the leader to append log data +// to the follower node. This function generates the response to be sent to the leader node. +// This is the response to the contact by the leader to assert it's leadership. +func (s *SimpleServer) AppendEntriesResponse(req *message.AppendEntriesRequest) *message.AppendEntriesResponse { + leaderTerm := req.GetTerm() + nodePersistentState := s.node.PersistentState + nodeTerm := nodePersistentState.CurrentTerm + // Return false if term is greater than currentTerm, + // if msg Log Index is greater than node commit Index, + // if term of msg at PrevLogIndex doesn't match prev Log Term stored by Leader. + if nodeTerm > leaderTerm || + req.GetPrevLogIndex() > s.node.VolatileState.CommitIndex || + nodePersistentState.Log[req.PrevLogIndex].Term != req.GetPrevLogTerm() { + s.node.log. + Debug(). + Str("self-id", s.node.PersistentState.SelfID.String()). + Str("returning failure to append entries to", string(req.GetLeaderID())). + Msg("append entries failure") + return &message.AppendEntriesResponse{ + Term: nodeTerm, + Success: false, + } + } + + entries := req.GetEntries() + if len(entries) > 0 { + nodePersistentState.mu.Lock() + if req.GetPrevLogIndex() < s.node.VolatileState.CommitIndex { + s.node.PersistentState.Log = s.node.PersistentState.Log[:req.GetPrevLogIndex()] + } + s.node.PersistentState.Log = append(s.node.PersistentState.Log, entries...) + s.node.PersistentState.mu.Unlock() + } + + if req.GetLeaderCommit() > s.node.VolatileState.CommitIndex { + nodeCommitIndex := req.GetLeaderCommit() + if int(req.GetLeaderCommit()) > len(s.node.PersistentState.Log) { + nodeCommitIndex = int32(len(s.node.PersistentState.Log)) + } + s.node.VolatileState.CommitIndex = nodeCommitIndex + /* FIX ISSUE #152 from this + commandEntries := getCommandFromLogs(entries) + succeeded := s.onReplication(commandEntries) + _ = succeeded + // succeeded returns the number of applied entries. + */ + } + + s.node.log. + Debug(). + Str("self-id", s.node.PersistentState.SelfID.String()). + Str("returning success to append entries to", string(req.GetLeaderID())). + Msg("append entries success") + + return &message.AppendEntriesResponse{ + Term: nodeTerm, + Success: true, + } + +} + +// func getCommandFromLogs(entries []*message.LogData) []*message.Command { +// var commandEntries []*message.Command +// for i := range entries { +// commandEntries = append(commandEntries, entries[i].Entry) +// } +// return commandEntries +// } diff --git a/internal/raft/append_entries_test.go b/internal/raft/append_entries_test.go new file mode 100644 index 00000000..d28e14f0 --- /dev/null +++ b/internal/raft/append_entries_test.go @@ -0,0 +1,132 @@ +package raft + +import ( + "net" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/cluster" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// TestAppendEntries function checks the correctnes of AppendEntriesResponse +// function. In this test function, we check how the function will respond to +// if node Term is less than leader node, node Log Index is less than leader +// commitIndex and checks if logs are appended correctly to node Log. +func TestAppendEntries(t *testing.T) { + t.SkipNow() + assert := assert.New(t) + + log := zerolog.Nop() + cluster := cluster.NewTCPCluster(log) + + conn1, conn2 := net.Pipe() + conn3, conn4 := net.Pipe() + tcp1int, tcp1ext := network.NewTCPConn(conn1), network.NewTCPConn(conn2) + tcp2int, tcp2ext := network.NewTCPConn(conn3), network.NewTCPConn(conn4) + defer func() { + _ = tcp1int.Close() + _ = tcp1ext.Close() + _ = tcp2int.Close() + _ = tcp2ext.Close() + }() + cluster.AddConnection(tcp1int) + cluster.AddConnection(tcp2int) + + // Created a mock node with default values for PersistentState + // and Volatile State. + // For Volatile State, CommitIndex given -1 to show no commit is + // applied as Log Index start with 0, so -1 show value before any + // log committed and same logic goes with LastApplied as -1 show + // no logs with given Index is applied to State Machine. + node := &Node{ + State: StateFollower.String(), + PersistentState: &PersistentState{ + CurrentTerm: 0, + VotedFor: nil, + SelfID: cluster.OwnID(), + PeerIPs: cluster.Nodes(), + }, + VolatileState: &VolatileState{ + CommitIndex: -1, + LastApplied: -1, + }, + } + + entries := []*message.LogData{ + message.NewLogData( + 2, + &message.Command_Scan{ + Table: &message.SimpleTable{ + Table: "table1", + }, + }, + ), + message.NewLogData( + 2, + &message.Command_Scan{ + Table: &message.SimpleTable{ + Table: "table2", + }, + }, + ), + } + // Creating a mock msg AppendEntriesRequest with default values + // Leader commit specifies the Index of Log commited by leader and + // entries include msg LogData sent to nodes. + msg := &message.AppendEntriesRequest{ + Term: 1, + PrevLogIndex: -1, + PrevLogTerm: 1, + Entries: entries, + LeaderCommit: 3, + } + + server := SimpleServer{ + node: node, + cluster: cluster, + log: log, + } + + node.PersistentState.CurrentTerm = 3 + res := server.AppendEntriesResponse(msg) + assert.False(res.Success, "Node Term is lesser than leader term") + msg.Term = 3 + msg.PrevLogIndex = 3 + node.VolatileState.CommitIndex = 2 + res = server.AppendEntriesResponse(msg) + assert.False(res.Success, "Node Log Index is lesser than"+ + "leader commit Index") + msg.Term = 2 + node.PersistentState.CurrentTerm = 2 + msg.PrevLogIndex = 1 + msg.PrevLogTerm = 1 + node.VolatileState.CommitIndex = 1 + node.PersistentState.Log = []*message.LogData{ + message.NewLogData( + 2, + &message.Command_Scan{ + Table: &message.SimpleTable{ + Table: "table1", + }, + }, + ), + message.NewLogData( + 2, + &message.Command_Scan{ + Table: &message.SimpleTable{ + Table: "table2", + }, + }, + ), + } + numberOfPersistentLog := len(node.PersistentState.Log) + res = server.AppendEntriesResponse(msg) + assert.True(res.Success, "Msg isn't appended to the node Logs") + assert.Equal(node.PersistentState.CurrentTerm, res.GetTerm(), + "Node doesn't have same term as leader") + assert.Equal(len(node.PersistentState.Log), + numberOfPersistentLog+len(entries), "LogData hasn't appended to the node ") +} diff --git a/internal/raft/cluster.go b/internal/raft/cluster.go new file mode 100644 index 00000000..903ef6cc --- /dev/null +++ b/internal/raft/cluster.go @@ -0,0 +1,21 @@ +package raft + +import ( + "context" + "io" + + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +//go:generate mockery -case=snake -name=Cluster + +// Cluster is a description of a cluster of servers. +type Cluster interface { + OwnID() id.ID + Nodes() []network.Conn + Receive(context.Context) (network.Conn, message.Message, error) + Broadcast(context.Context, message.Message) error + io.Closer +} diff --git a/internal/raft/cluster/cluster.go b/internal/raft/cluster/cluster.go new file mode 100644 index 00000000..103d058f --- /dev/null +++ b/internal/raft/cluster/cluster.go @@ -0,0 +1,53 @@ +package cluster + +import ( + "context" + "io" + + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// ConnHandler is a function that handles a connection and performs a +// handshake. If an error occurs, considering closing the connection. If you +// want the connection to be remembered by the cluster as node, you must add it +// with (cluster.Cluster).AddConnection(network.Conn). +type ConnHandler func(Cluster, network.Conn) + +// Cluster describes a raft cluster. It sometimes has a leader and consists of +// nodes. +type Cluster interface { + // Nodes returns all nodes in the cluster (except this one), including the + // leader node. + Nodes() []network.Conn + // Receive blocks until any connection in the cluster has sent a message to + // this node. It will return the connection and the message, with respect to + // the given context. + Receive(context.Context) (network.Conn, message.Message, error) + // Broadcast sends the given message to all other nodes in this cluster, + // with respect to the given context. + Broadcast(context.Context, message.Message) error + + // OwnID returns the global ID of this node. + OwnID() id.ID + // Join joins the cluster at the given address. The given address may be the + // address and port of any of the nodes in the existing cluster. + Join(context.Context, string) error + // Open creates a new cluster and opens it on the given address. This + // creates a server that will listen for incoming connections. + Open(context.Context, string) error + // AddConnection adds the connection to the cluster. It is considered + // another node in the cluster. + AddConnection(network.Conn) + // RemoveConnection closes the connection and removes it from the cluster. + RemoveConnection(network.Conn) + // OnConnect allows to set a connection hook. This is useful when + // implementing a custom handshake for connecting to the cluster. By default + // on connect will just remember the connection as cluster node. When this + // is set explicitely, (cluster.Cluster).AddConnection(network.Conn) must be + // called, otherwise the connection will not be added to the cluster. + OnConnect(ConnHandler) + + io.Closer +} diff --git a/internal/raft/cluster/doc.go b/internal/raft/cluster/doc.go new file mode 100644 index 00000000..d7994404 --- /dev/null +++ b/internal/raft/cluster/doc.go @@ -0,0 +1,3 @@ +// Package cluster provides easily usable functionality for interacting with +// other nodes in a raft cluster. +package cluster diff --git a/internal/raft/cluster/error.go b/internal/raft/cluster/error.go new file mode 100644 index 00000000..633f0916 --- /dev/null +++ b/internal/raft/cluster/error.go @@ -0,0 +1,12 @@ +package cluster + +// Error is a helper type for creating constant errors. +type Error string + +func (e Error) Error() string { return string(e) } + +const ( + // ErrTimeout indicates, that a the operation took longer than allowed. + // Maybe there was a deadline from a context. + ErrTimeout Error = "timeout" +) diff --git a/internal/raft/cluster/tcp_cluster.go b/internal/raft/cluster/tcp_cluster.go new file mode 100644 index 00000000..53ff786b --- /dev/null +++ b/internal/raft/cluster/tcp_cluster.go @@ -0,0 +1,259 @@ +package cluster + +import ( + "context" + "fmt" + "sync" + "sync/atomic" + + "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/message" + "golang.org/x/sync/errgroup" +) + +const ( + tcpClusterMessageQueueBufferSize = 5 +) + +var _ Cluster = (*tcpCluster)(nil) + +type tcpCluster struct { + log zerolog.Logger + + connLock sync.Mutex + conns []network.Conn + + onConnect ConnHandler + + server network.Server + messages chan incomingPayload + started chan struct{} + startedClosed bool + closed int32 + + // lock needed for atomic write on startedClosed. + mu sync.Mutex +} + +type incomingPayload struct { + origin network.Conn + payload []byte +} + +// NewTCPCluster creates a new cluster that uses TCP connections to communicate +// with other nodes. +func NewTCPCluster(log zerolog.Logger) Cluster { + return &tcpCluster{ + log: log.With().Str("cluster", "tcp").Logger(), + onConnect: func(c Cluster, conn network.Conn) { c.AddConnection(conn) }, + server: network.NewTCPServer(log), + messages: make(chan incomingPayload, tcpClusterMessageQueueBufferSize), + started: make(chan struct{}), + startedClosed: false, + } +} + +func (c *tcpCluster) OnConnect(handler ConnHandler) { + c.onConnect = handler +} + +func (c *tcpCluster) Join(ctx context.Context, addr string) error { + // connect to the given address + conn, err := network.DialTCP(ctx, c.server.OwnID(), addr) + if err != nil { + return fmt.Errorf("dial tcp: %w", err) + } + c.AddConnection(conn) + + // We have now joined the cluster, start the common procedure for network + // operations, like listening to incoming connections, messages etc. + go c.start() + + return nil +} + +func (c *tcpCluster) Open(ctx context.Context, addr string) error { + go func() { + _ = c.server.Open(addr) + }() + + select { + case <-ctx.Done(): + _ = c.Close() // will also close the server that we just tried to open + return ErrTimeout + case <-c.server.Listening(): + } + go c.start() + return nil +} + +// Nodes returns a copy of the connections that the cluster currently holds. +func (c *tcpCluster) Nodes() []network.Conn { + c.connLock.Lock() + defer c.connLock.Unlock() + + nodes := make([]network.Conn, len(c.conns)) + copy(nodes, c.conns) + return nodes +} + +func (c *tcpCluster) OwnID() id.ID { + return c.server.OwnID() +} + +func (c *tcpCluster) Receive(ctx context.Context) (network.Conn, message.Message, error) { + incoming, ok := <-c.messages + if !ok { + return nil, nil, fmt.Errorf("channel closed") + } + msg, err := message.Unmarshal(incoming.payload) + if err != nil { + return nil, nil, fmt.Errorf("unmarshal: %w", err) + } + return incoming.origin, msg, nil +} + +func (c *tcpCluster) Broadcast(ctx context.Context, msg message.Message) error { + c.connLock.Lock() + defer c.connLock.Unlock() + + errs, _ := errgroup.WithContext(ctx) + for _, conn := range c.conns { + errs.Go(func() error { + if err := c.sendMessage(ctx, conn, msg); err != nil { + return fmt.Errorf("send message: %w", err) + } + return nil + }) + } + return errs.Wait() +} + +// Close will shut down the cluster. This means: +// +// * the cluster's status is set to closed +// * all connections in the cluster's connection list are closed (not removed) +// * the underlying network server is closed +// * the cluster's message queue is closed +// +// After Close is called on this cluster, it is no longer usable. +func (c *tcpCluster) Close() error { + atomic.StoreInt32(&c.closed, 1) + + // close all connections + var errs errgroup.Group + c.connLock.Lock() + for _, conn := range c.conns { + errs.Go(conn.Close) + } + c.connLock.Unlock() + + errs.Go(c.server.Close) + + // close the message queue + close(c.messages) + + return errs.Wait() +} + +// addConnection will add the connection to the list of connections of this +// cluster. It will also start a goroutine that reads from the connection. That +// goroutine will push back read data. +func (c *tcpCluster) AddConnection(conn network.Conn) { + c.connLock.Lock() + defer c.connLock.Unlock() + + c.conns = append(c.conns, conn) + go c.receiveMessages(conn) +} + +// RemoveConnection will attempt to remove the given connection from the list of +// connections in this cluster. If the connection was found, it will be removed +// AND CLOSED. If the connection was NOT found, it will NOT be closed. +func (c *tcpCluster) RemoveConnection(conn network.Conn) { + c.connLock.Lock() + defer c.connLock.Unlock() + + for i, node := range c.conns { + if node.RemoteID() == conn.RemoteID() { + c.conns[i] = c.conns[len(c.conns)-1] + c.conns[len(c.conns)-1] = nil + c.conns = c.conns[:len(c.conns)-1] + + _ = conn.Close() + return + } + } +} + +func (c *tcpCluster) sendMessage(ctx context.Context, conn network.Conn, msg message.Message) error { + msgData, err := message.Marshal(msg) + if err != nil { + return fmt.Errorf("marshal: %w", err) + } + + if err := conn.Send(ctx, msgData); err != nil { + return fmt.Errorf("send: %w", err) + } + return nil +} + +func (c *tcpCluster) start() { + // On connect, execute the on-connect hook. + c.server.OnConnect(func(conn network.Conn) { + if c.onConnect != nil { + c.onConnect(c, conn) + } + }) + + // signal all waiting receive message goroutines that the server is now + // started and they can start pushing messages onto the queue + c.mu.Lock() + defer c.mu.Unlock() + if !c.startedClosed { + close(c.started) + c.startedClosed = true + } +} + +// receiveMessages will wait for the cluster to be started, and then, while the +// cluster is not closed, attempt to read data from the connection. If the read +// times out, it tries again indefinitely. If an error occurs during the read, +// and the server is already closed, nothing happens, but this method returns. +// If an error occurs during the read, and the server is NOT closed, the +// connection will be removed with (*tcpCluster).RemoveConnection, and the error +// will be logged with error level. After that, this method will return. +func (c *tcpCluster) receiveMessages(conn network.Conn) { + <-c.started // wait for the server to be started + + for atomic.LoadInt32(&c.closed) == 0 { + // receive data from the connection + data, err := conn.Receive(context.TODO()) + if err != nil { + if err == network.ErrTimeout { + // didn't receive a message within the timeout, try again + continue + } + if atomic.LoadInt32(&c.closed) == 1 { + // server is closed, no reason to log errors from connections + // that we failed to read from, but break the read loop and + // terminate this goroutine + return + } + c.RemoveConnection(conn) // also closes the connection + c.log.Error(). + Err(err). + Str("fromID", conn.RemoteID().String()). + Msg("receive failed, removing connection") + return // abort this goroutine + } + + // push payload and connection onto the message queue + c.messages <- incomingPayload{ + origin: conn, + payload: data, + } + } +} diff --git a/internal/raft/cluster/tcp_cluster_test.go b/internal/raft/cluster/tcp_cluster_test.go new file mode 100644 index 00000000..83d87bcf --- /dev/null +++ b/internal/raft/cluster/tcp_cluster_test.go @@ -0,0 +1,94 @@ +package cluster_test + +import ( + "context" + "net" + "sync" + "testing" + "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/cluster" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +func TestTCPClusterCommunication(t *testing.T) { + assert := assert.New(t) + + ctx := context.Background() + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + cluster := cluster.NewTCPCluster(zerolog.Nop()) + defer func() { + _ = cluster.Close() + }() + assert.Empty(cluster.Nodes()) + + err := cluster.Open(ctx, ":0") + assert.NoError(err) + + conn1, conn2 := net.Pipe() + tcp1, tcp2 := network.NewTCPConn(conn1), network.NewTCPConn(conn2) + defer func() { + _ = tcp1.Close() + _ = tcp2.Close() + }() + + cluster.AddConnection(tcp1) + assert.Len(cluster.Nodes(), 1) + + t.Run("Broadcast", _TestTCPClusterBroadcast(ctx, cluster, tcp2)) + t.Run("Receive", _TestTCPClusterReceive(ctx, cluster, tcp1, tcp2)) +} + +func _TestTCPClusterBroadcast(ctx context.Context, cluster cluster.Cluster, externalConn network.Conn) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + err := cluster.Broadcast(ctx, message.NewTestMessage("Hello, World!")) + assert.NoError(err) + wg.Done() + }() + + data, err := externalConn.Receive(ctx) + assert.NoError(err) + + wg.Wait() + msg, err := message.Unmarshal(data) + assert.NoError(err) + assert.Equal(message.KindTestMessage, msg.Kind()) + assert.IsType(&message.TestMessage{}, msg) + assert.Equal("Hello, World!", msg.(*message.TestMessage).GetData()) + } +} + +func _TestTCPClusterReceive(ctx context.Context, cluster cluster.Cluster, internalConn, externalConn network.Conn) func(*testing.T) { + return func(t *testing.T) { + assert := assert.New(t) + + data, err := message.Marshal(message.NewTestMessage("Hello, World!")) + assert.NoError(err) + + // This should not block, since the cluster uses a buffered message + // queue. If it blocks however, it will run into a timeout. + err = externalConn.Send(ctx, data) + assert.NoError(err) + + conn, msg, err := cluster.Receive(ctx) + assert.NoError(err) + // The external conn ID is not equal to the conn.ID(), because it did + // not connect to a network.Server with network.DialTCP, and thus had no + // chance of exchanging the ID. When connecting to the cluster with + // cluster.Join or network.DialTCP however, this ID will be the same. + assert.Equal(internalConn.RemoteID(), conn.RemoteID()) + assert.Equal(message.KindTestMessage, msg.Kind()) + assert.IsType(&message.TestMessage{}, msg) + assert.Equal("Hello, World!", msg.(*message.TestMessage).GetData()) + } +} diff --git a/internal/raft/cluster/test_framework.go b/internal/raft/cluster/test_framework.go new file mode 100644 index 00000000..664b4ee9 --- /dev/null +++ b/internal/raft/cluster/test_framework.go @@ -0,0 +1,135 @@ +package cluster + +import ( + "context" + "net" + "strconv" + + "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/network" +) + +// TestNetwork encompasses the entire network on which +// the tests will be performed. +type TestNetwork struct { + Clusters []*TestCluster +} + +// TestCluster describes a single cluster and all the +// nodes in it. +type TestCluster struct { + Cluster Cluster + Nodes []*network.TestNode +} + +// NewTestCluster creates a cluster and joins all the nodes onto the cluster. +func NewTestCluster(nodes []*network.TestNode, log zerolog.Logger) (*TestCluster, error) { + cluster := NewTCPCluster(log) + err := joinCluster(nodes, cluster) + if err != nil { + return nil, err + } + return &TestCluster{ + Cluster: cluster, + Nodes: nodes, + }, nil +} + +// joinCluster allows a set of nodes to join a cluster. +func joinCluster( + tcpServers []*network.TestNode, + clstr Cluster, +) error { + ctx := context.TODO() + for i := 0; i < len(tcpServers); i++ { + err := clstr.Join(ctx, tcpServers[i].Node.Addr().String()) + if err != nil { + return err + } + } + return nil +} + +// NewTestNetwork returns a ready to use network. +// +// It creates the necessary amount of nodes, links them +// appropriately and then creates clusters based on the +// nodes. +func NewTestNetwork(number int, log zerolog.Logger) (*TestNetwork, error) { + + // Create the number of nodes needed. + IP := "127.0.0.1" + basePort := 12000 + + var nodes []*network.TestNode + for i := 0; i < number; i++ { + port := basePort + i + node, err := network.NewTestNode(IP, strconv.Itoa(port), log) + if err != nil { + return nil, err + } + nodes = append(nodes, node) + } + + linkNodes(nodes) + + // Using the nodes, group them into clusters. + // Each node "sees" the other nodes as a cluster, + // thus we have number of clusters equal to the nodes. + var clusters []*TestCluster + + for i := 0; i < number; i++ { + + otherNodes := exclude(nodes, i) + + clstr, err := NewTestCluster(otherNodes, log) + if err != nil { + return nil, err + } + + clusters = append(clusters, clstr) + } + return &TestNetwork{ + Clusters: clusters, + }, nil +} + +// exclude excludes the i'th element from the slice. +func exclude(s []*network.TestNode, i int) []*network.TestNode { + l := len(s) + + rs := make([]*network.TestNode, l) + copy(rs, s) + + return append(rs[:i], rs[i+1:]...) +} + +// linkNodes links the network of nodes together with a +// net.Pipe connection over the network.Conn. +// +// TCP connections are created and each node keeps one end +// of the connection and another end of the pipe is added +// to the other nodes list. +func linkNodes(nodes []*network.TestNode) { + for i := 0; i < len(nodes)-1; i++ { + numConns := len(nodes) - i - 1 + tcpConnSelf, tcpConnOther := createTCPConns(numConns) + nodes[i].Conns = append(nodes[i].Conns, tcpConnSelf...) + for j := i + 1; j < len(nodes); j++ { + nodes[j].Conns = append(nodes[j].Conns, tcpConnOther[j-i-1]) + } + } +} + +// createTCPConns creates and returns 2 ends of a pipe of a TCP connection. +func createTCPConns(count int) ([]network.Conn, []network.Conn) { + var tcpSelfSlice, tcpOtherSlice []network.Conn + for count > 0 { + c1, c2 := net.Pipe() + tcpSelf, tcpOther := network.NewTCPConn(c1), network.NewTCPConn(c2) + tcpSelfSlice = append(tcpSelfSlice, tcpSelf) + tcpOtherSlice = append(tcpOtherSlice, tcpOther) + count-- + } + return tcpSelfSlice, tcpOtherSlice +} diff --git a/internal/raft/doc.go b/internal/raft/doc.go new file mode 100644 index 00000000..9a9b577f --- /dev/null +++ b/internal/raft/doc.go @@ -0,0 +1,3 @@ +// Package raft implements the raft consensus protocol. +// This package provides API to run a raft cluster. +package raft diff --git a/internal/raft/error.go b/internal/raft/error.go new file mode 100644 index 00000000..a508ed1b --- /dev/null +++ b/internal/raft/error.go @@ -0,0 +1,11 @@ +package raft + +import "fmt" + +type multiError []error + +var _ error = (*multiError)(nil) + +func (e multiError) Error() string { + return fmt.Sprintf("multiple errors: %v", []error(e)) +} diff --git a/internal/raft/example_test.go b/internal/raft/example_test.go new file mode 100644 index 00000000..1146bccf --- /dev/null +++ b/internal/raft/example_test.go @@ -0,0 +1,28 @@ +package raft + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + networkmocks "github.com/tomarrell/lbadd/internal/network/mocks" + "github.com/tomarrell/lbadd/internal/raft/mocks" +) + +func TestExample(t *testing.T) { + conn := new(networkmocks.Conn) + // mock call to RemoteID + id := id.Create() + conn. + On("RemoteID"). + Return(id) + + c := new(mocks.Cluster) + // mock call to Nodes + c. + On("Nodes"). + Return([]network.Conn{conn}) + + assert.Equal(t, conn.RemoteID().String(), c.Nodes()[0].RemoteID().String()) +} diff --git a/internal/raft/follower.go b/internal/raft/follower.go new file mode 100644 index 00000000..93f9c86a --- /dev/null +++ b/internal/raft/follower.go @@ -0,0 +1,14 @@ +package raft + +// becomeFollower converts a leader to a follower. +// After this function is executed, the node goes back to the loop in raft.go +// thus resuming normal operations. +func (node *Node) becomeFollower() { + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Msg("becoming follower") + node.PersistentState.LeaderID = nil + node.PersistentState.VotedFor = nil + node.State = StateFollower.String() +} diff --git a/internal/raft/leader.go b/internal/raft/leader.go new file mode 100644 index 00000000..e4b54b42 --- /dev/null +++ b/internal/raft/leader.go @@ -0,0 +1,175 @@ +package raft + +import ( + "context" + "time" + + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// startLeader begins the leaders operations. +// The node passed as argument is the leader node. +// The leader begins by sending append entries RPC to the nodes. +// The leader sends periodic append entries request to the +// followers to keep them alive. +// Empty append entries request are also called heartbeats. +// The data that goes in the append entries request is determined by +// existance of data in the LogChannel channel. +func (s *SimpleServer) startLeader() { + + s.lock.Lock() + s.node.log. + Debug(). + Str("self-id", s.node.PersistentState.SelfID.String()). + Msg("starting leader election proceedings") + s.lock.Unlock() + + go func() { + // The loop that the leader stays in until it's functioning properly. + // The goal of this loop is to maintain raft in it's working phase; + // periodically sending heartbeats/appendEntries. + // This loop goes on until this node is the leader. + for { + // Send heartbeats every 50ms. + <-time.NewTimer(50 * time.Millisecond).C + + // Before continuing the operations, check whether + // the server is not closed. + s.lock.Lock() + if s.node == nil { + s.lock.Unlock() + return + } + s.node.PersistentState.mu.Lock() + if s.node.State != StateLeader.String() { + s.node.PersistentState.mu.Unlock() + return + } + s.node.PersistentState.mu.Unlock() + + s.node.sendHeartBeats() + s.lock.Unlock() + + if s.onAppendEntries != nil { + s.onAppendEntries() + } + } + }() +} + +func (node *Node) sendHeartBeats() { + ctx := context.TODO() + + node.PersistentState.mu.Lock() + savedCurrentTerm := node.PersistentState.CurrentTerm + node.PersistentState.mu.Unlock() + + var appendEntriesRequest *message.AppendEntriesRequest + + // Parallely send AppendEntriesRPC to all followers. + for i := range node.PersistentState.PeerIPs { + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Msg("sending heartbeats") + go func(i int) { + node.PersistentState.mu.Lock() + defer node.PersistentState.mu.Unlock() + + nextIndex := node.VolatileStateLeader.NextIndex[i] + prevLogIndex := nextIndex + prevLogTerm := -1 + if prevLogIndex >= 0 { + prevLogTerm = int(node.PersistentState.Log[prevLogIndex].Term) + } + commitIndex := node.VolatileState.CommitIndex + selfID := node.PersistentState.SelfID + + // Logs are included from the nextIndex value to the current appended values + // in the leader node. If there are none, no logs will be appended. + var entries []*message.LogData + if nextIndex >= 0 { + entries = node.PersistentState.Log[nextIndex:] + } + + appendEntriesRequest = message.NewAppendEntriesRequest( + savedCurrentTerm, + selfID, + int32(prevLogIndex), + int32(prevLogTerm), + entries, + commitIndex, + ) + + payload, err := message.Marshal(appendEntriesRequest) + if err != nil { + node.log. + Err(err). + Str("Node", node.PersistentState.SelfID.String()). + Msg("error") + return + } + + err = node.PersistentState.PeerIPs[i].Send(ctx, payload) + if err != nil { + node.log. + Err(err). + Str("Node", selfID.String()). + Msg("error") + return + } + + node.log. + Debug(). + Str("self-id", selfID.String()). + Str("sent to", node.PersistentState.PeerIPs[i].RemoteID().String()). + Msg("sent heartbeat to peer") + + res, err := node.PersistentState.PeerIPs[i].Receive(ctx) + if err != nil { + node.log. + Err(err). + Str("Node", selfID.String()). + Msg("error") + return + } + + resP, err := message.Unmarshal(res) + if err != nil { + node.log. + Err(err). + Str("Node", selfID.String()). + Msg("error") + return + } + + appendEntriesResponse := resP.(*message.AppendEntriesResponse) + + // If the term in the other node is greater than this node's term, + // it means that this node is not up to date and has to step down + // from being a leader. + if appendEntriesResponse.Term > savedCurrentTerm { + node.log.Debug(). + Str(node.PersistentState.SelfID.String(), "stale term"). + Str("following newer node", node.PersistentState.PeerIPs[i].RemoteID().String()) + node.becomeFollower() + return + } + + if node.State == StateLeader.String() && appendEntriesResponse.Term == savedCurrentTerm { + if appendEntriesResponse.Success { + node.VolatileStateLeader.NextIndex[i] = nextIndex + len(entries) + } else { + // If this appendEntries request failed, + // proceed and retry in the next cycle. + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Str("received failure to append entries from", node.PersistentState.PeerIPs[i].RemoteID().String()). + Msg("failed to append entries") + } + + } + }(i) + } +} diff --git a/internal/raft/leader_election.go b/internal/raft/leader_election.go new file mode 100644 index 00000000..cb014fb0 --- /dev/null +++ b/internal/raft/leader_election.go @@ -0,0 +1,105 @@ +package raft + +import ( + "context" + "sync/atomic" + + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// StartElection enables a node in the cluster to start the election. +// It returns an error based on what happened if it cannot start the election.(?) +// The function caller doesn't need to wait for a voting response from this function, +// the function triggers the necessary functions responsible to continue the raft cluster +// into it's working stage if the node won the election. +func (s *SimpleServer) StartElection(ctx context.Context) { + + s.lock.Lock() + s.node.PersistentState.mu.Lock() + s.node.State = StateCandidate.String() + s.node.PersistentState.CurrentTerm++ + var lastLogTerm, lastLogIndex int32 + savedCurrentTerm := s.node.PersistentState.CurrentTerm + if len(s.node.PersistentState.Log) == 0 { + lastLogTerm = 0 + } else { + lastLogTerm = s.node.PersistentState.Log[len(s.node.PersistentState.Log)].Term + } + lastLogIndex = int32(len(s.node.PersistentState.Log)) + selfID := s.node.PersistentState.SelfID + numNodes := s.node.PersistentState.PeerIPs + s.node.log. + Debug(). + Str("self-id", selfID.String()). + Int32("term", s.node.PersistentState.CurrentTerm+1). + Msg("starting election") + s.node.PersistentState.mu.Unlock() + s.lock.Unlock() + + var votes int32 + + for i := range numNodes { + // Parallely request votes from the peers. + go func(i int) { + req := message.NewRequestVoteRequest( + savedCurrentTerm, + selfID, + lastLogIndex, + lastLogTerm, + ) + s.lock.Lock() + if s.node == nil { + return + } + s.node.log. + Debug(). + Str("self-id", selfID.String()). + Str("request-vote sent to", s.node.PersistentState.PeerIPs[i].RemoteID().String()). + Msg("request vote") + + nodeConn := s.node.PersistentState.PeerIPs[i] + s.lock.Unlock() + + res, err := s.RequestVote(ctx, nodeConn, req) + // If there's an error, the vote is considered to be not casted by the node. + // Worst case, there will be a re-election; the errors might be from network or + // data consistency errors, which will be sorted by a re-election. + // This decision was taken because, StartElection returning an error is not feasible. + if err == nil && res.VoteGranted { + s.lock.Lock() + s.node.log. + Debug(). + Str("received vote from", s.node.PersistentState.PeerIPs[i].RemoteID().String()). + Msg("voting from peer") + s.lock.Unlock() + votesRecieved := atomic.AddInt32(&votes, 1) + + // Check whether this node has already voted. + // Else it can vote for itself. + s.node.PersistentState.mu.Lock() + defer s.node.PersistentState.mu.Unlock() + + if s.node.PersistentState.VotedFor == nil { + s.node.PersistentState.VotedFor = selfID + s.node.log. + Debug(). + Str("self-id", selfID.String()). + Msg("node voting for itself") + votesRecieved++ + } + + if votesRecieved > int32(len(s.node.PersistentState.PeerIPs)/2) && s.node.State != StateLeader.String() { + // This node has won the election. + s.node.State = StateLeader.String() + s.node.PersistentState.LeaderID = selfID + s.node.log. + Debug(). + Str("self-id", selfID.String()). + Msg("node elected leader") + s.startLeader() + return + } + } + }(i) + } +} diff --git a/internal/raft/leader_election_test.go b/internal/raft/leader_election_test.go new file mode 100644 index 00000000..653c35cf --- /dev/null +++ b/internal/raft/leader_election_test.go @@ -0,0 +1,97 @@ +package raft + +import ( + "context" + "net" + "os" + "sync" + "testing" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/cluster" + "github.com/tomarrell/lbadd/internal/raft/message" + "gotest.tools/assert/cmp" +) + +func Test_LeaderElection(t *testing.T) { + t.SkipNow() + assert := assert.New(t) + + zerolog.New(os.Stdout).With(). + Str("foo", "bar"). + Logger() + + ctx := context.TODO() + log := zerolog.New(os.Stdout).With().Logger().Level(zerolog.GlobalLevel()) + cluster := cluster.NewTCPCluster(log) + + conn1, conn2 := net.Pipe() + conn3, conn4 := net.Pipe() + tcp1int, tcp1ext := network.NewTCPConn(conn1), network.NewTCPConn(conn2) + tcp2int, tcp2ext := network.NewTCPConn(conn3), network.NewTCPConn(conn4) + defer func() { + _ = tcp1int.Close() + _ = tcp1ext.Close() + _ = tcp2int.Close() + _ = tcp2ext.Close() + }() + cluster.AddConnection(tcp1int) + cluster.AddConnection(tcp2int) + + node := NewRaftNode(cluster) + + var wg sync.WaitGroup + + wg.Add(1) + go func() { + res, err := tcp1ext.Receive(ctx) + assert.Nil(err) + + msg, err := message.Unmarshal(res) + assert.Nil(err) + _ = msg + _ = res + resP := message.NewRequestVoteResponse(1, true) + + payload, err := message.Marshal(resP) + assert.Nil(err) + + err = tcp1ext.Send(ctx, payload) + assert.Nil(err) + wg.Done() + }() + + wg.Add(1) + go func() { + res, err := tcp2ext.Receive(ctx) + assert.Nil(err) + + msg, err := message.Unmarshal(res) + assert.Nil(err) + _ = msg + _ = res + resP := message.NewRequestVoteResponse(1, true) + + payload, err := message.Marshal(resP) + assert.Nil(err) + err = tcp2ext.Send(ctx, payload) + assert.Nil(err) + wg.Done() + }() + + server := SimpleServer{ + node: node, + cluster: cluster, + log: log, + } + + server.StartElection(ctx) + + wg.Wait() + + node.PersistentState.mu.Lock() + assert.True(cmp.Equal(node.PersistentState.SelfID, node.PersistentState.LeaderID)().Success()) + node.PersistentState.mu.Unlock() +} diff --git a/internal/raft/message/append_entries.go b/internal/raft/message/append_entries.go new file mode 100644 index 00000000..816f739e --- /dev/null +++ b/internal/raft/message/append_entries.go @@ -0,0 +1,53 @@ +package message + +import ( + "github.com/tomarrell/lbadd/internal/compiler/command" + "github.com/tomarrell/lbadd/internal/id" +) + +//go:generate protoc --go_out=. append_entries.proto + +var _ Message = (*AppendEntriesRequest)(nil) + +// NewAppendEntriesRequest creates a new append-entries-request message with the +// given parameters. +func NewAppendEntriesRequest(term int32, leaderID id.ID, prevLogIndex int32, prevLogTerm int32, entries []*LogData, leaderCommit int32) *AppendEntriesRequest { + return &AppendEntriesRequest{ + Term: term, + LeaderID: leaderID.Bytes(), + PrevLogIndex: prevLogIndex, + PrevLogTerm: prevLogTerm, + Entries: entries, + LeaderCommit: leaderCommit, + } +} + +// Kind returns KindAppendEntriesRequest. +func (*AppendEntriesRequest) Kind() Kind { + return KindAppendEntriesRequest +} + +// NewLogData creates a new log-data object, which can be used for an +// append-entries-request message. +func NewLogData(term int32, data command.Command) *LogData { + msg, _ := ConvertCommandToMessage(data) + + return &LogData{ + Term: term, + Entry: msg.(*Command), + } +} + +// NewAppendEntriesResponse creates a new append-entries-response message with +// the given parameters. +func NewAppendEntriesResponse(term int32, success bool) *AppendEntriesResponse { + return &AppendEntriesResponse{ + Term: term, + Success: success, + } +} + +// Kind returns KindAppendEntriesResponse. +func (*AppendEntriesResponse) Kind() Kind { + return KindAppendEntriesResponse +} diff --git a/internal/raft/message/append_entries.pb.go b/internal/raft/message/append_entries.pb.go new file mode 100644 index 00000000..35d4d7b7 --- /dev/null +++ b/internal/raft/message/append_entries.pb.go @@ -0,0 +1,350 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: append_entries.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type AppendEntriesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + LeaderID []byte `protobuf:"bytes,2,opt,name=leaderID,proto3" json:"leaderID,omitempty"` + PrevLogIndex int32 `protobuf:"varint,3,opt,name=prevLogIndex,proto3" json:"prevLogIndex,omitempty"` + PrevLogTerm int32 `protobuf:"varint,4,opt,name=prevLogTerm,proto3" json:"prevLogTerm,omitempty"` + Entries []*LogData `protobuf:"bytes,5,rep,name=Entries,proto3" json:"Entries,omitempty"` // Entries are the log entries in the node. + LeaderCommit int32 `protobuf:"varint,6,opt,name=leaderCommit,proto3" json:"leaderCommit,omitempty"` // LeaderCommit is the Leader's commit index. +} + +func (x *AppendEntriesRequest) Reset() { + *x = AppendEntriesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_append_entries_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesRequest) ProtoMessage() {} + +func (x *AppendEntriesRequest) ProtoReflect() protoreflect.Message { + mi := &file_append_entries_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesRequest.ProtoReflect.Descriptor instead. +func (*AppendEntriesRequest) Descriptor() ([]byte, []int) { + return file_append_entries_proto_rawDescGZIP(), []int{0} +} + +func (x *AppendEntriesRequest) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *AppendEntriesRequest) GetLeaderID() []byte { + if x != nil { + return x.LeaderID + } + return nil +} + +func (x *AppendEntriesRequest) GetPrevLogIndex() int32 { + if x != nil { + return x.PrevLogIndex + } + return 0 +} + +func (x *AppendEntriesRequest) GetPrevLogTerm() int32 { + if x != nil { + return x.PrevLogTerm + } + return 0 +} + +func (x *AppendEntriesRequest) GetEntries() []*LogData { + if x != nil { + return x.Entries + } + return nil +} + +func (x *AppendEntriesRequest) GetLeaderCommit() int32 { + if x != nil { + return x.LeaderCommit + } + return 0 +} + +type LogData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + Entry *Command `protobuf:"bytes,2,opt,name=Entry,proto3" json:"Entry,omitempty"` // Each is a compiled sql stmt +} + +func (x *LogData) Reset() { + *x = LogData{} + if protoimpl.UnsafeEnabled { + mi := &file_append_entries_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LogData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LogData) ProtoMessage() {} + +func (x *LogData) ProtoReflect() protoreflect.Message { + mi := &file_append_entries_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LogData.ProtoReflect.Descriptor instead. +func (*LogData) Descriptor() ([]byte, []int) { + return file_append_entries_proto_rawDescGZIP(), []int{1} +} + +func (x *LogData) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *LogData) GetEntry() *Command { + if x != nil { + return x.Entry + } + return nil +} + +type AppendEntriesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` // Term is the responder node's current term. + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` // Success returns true if the log matching property holds good. +} + +func (x *AppendEntriesResponse) Reset() { + *x = AppendEntriesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_append_entries_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AppendEntriesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AppendEntriesResponse) ProtoMessage() {} + +func (x *AppendEntriesResponse) ProtoReflect() protoreflect.Message { + mi := &file_append_entries_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AppendEntriesResponse.ProtoReflect.Descriptor instead. +func (*AppendEntriesResponse) Descriptor() ([]byte, []int) { + return file_append_entries_proto_rawDescGZIP(), []int{2} +} + +func (x *AppendEntriesResponse) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *AppendEntriesResponse) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +var File_append_entries_proto protoreflect.FileDescriptor + +var file_append_entries_proto_rawDesc = []byte{ + 0x0a, 0x14, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, + 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdc, + 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x6c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x76, 0x4c, + 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, + 0x72, 0x65, 0x76, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x70, + 0x72, 0x65, 0x76, 0x4c, 0x6f, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x4c, 0x6f, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x12, 0x2a, 0x0a, + 0x07, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x44, 0x61, 0x74, 0x61, + 0x52, 0x07, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0c, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x45, 0x0a, + 0x07, 0x4c, 0x6f, 0x67, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x26, 0x0a, 0x05, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x05, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x22, 0x45, 0x0a, 0x15, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x45, 0x6e, + 0x74, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, + 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x0b, 0x5a, 0x09, 0x2e, + 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_append_entries_proto_rawDescOnce sync.Once + file_append_entries_proto_rawDescData = file_append_entries_proto_rawDesc +) + +func file_append_entries_proto_rawDescGZIP() []byte { + file_append_entries_proto_rawDescOnce.Do(func() { + file_append_entries_proto_rawDescData = protoimpl.X.CompressGZIP(file_append_entries_proto_rawDescData) + }) + return file_append_entries_proto_rawDescData +} + +var file_append_entries_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_append_entries_proto_goTypes = []interface{}{ + (*AppendEntriesRequest)(nil), // 0: message.AppendEntriesRequest + (*LogData)(nil), // 1: message.LogData + (*AppendEntriesResponse)(nil), // 2: message.AppendEntriesResponse + (*Command)(nil), // 3: message.Command +} +var file_append_entries_proto_depIdxs = []int32{ + 1, // 0: message.AppendEntriesRequest.Entries:type_name -> message.LogData + 3, // 1: message.LogData.Entry:type_name -> message.Command + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_append_entries_proto_init() } +func file_append_entries_proto_init() { + if File_append_entries_proto != nil { + return + } + file_command_proto_init() + if !protoimpl.UnsafeEnabled { + file_append_entries_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_append_entries_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LogData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_append_entries_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AppendEntriesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_append_entries_proto_rawDesc, + NumEnums: 0, + NumMessages: 3, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_append_entries_proto_goTypes, + DependencyIndexes: file_append_entries_proto_depIdxs, + MessageInfos: file_append_entries_proto_msgTypes, + }.Build() + File_append_entries_proto = out.File + file_append_entries_proto_rawDesc = nil + file_append_entries_proto_goTypes = nil + file_append_entries_proto_depIdxs = nil +} diff --git a/internal/raft/message/append_entries.proto b/internal/raft/message/append_entries.proto new file mode 100644 index 00000000..286f31d2 --- /dev/null +++ b/internal/raft/message/append_entries.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; +import "command.proto"; + +message AppendEntriesRequest { + int32 term = 1; + bytes leaderID = 2; + int32 prevLogIndex = 3; + int32 prevLogTerm = 4; + repeated LogData Entries = 5; // Entries are the log entries in the node. + int32 leaderCommit = 6; // LeaderCommit is the Leader's commit index. +} + +message LogData { + int32 term = 1; + Command Entry = 2; // Each is a compiled sql stmt +} + +message AppendEntriesResponse { + int32 term = 1; // Term is the responder node's current term. + bool success = 2; // Success returns true if the log matching property holds good. +} \ No newline at end of file diff --git a/internal/raft/message/command.go b/internal/raft/message/command.go new file mode 100644 index 00000000..2223d8a0 --- /dev/null +++ b/internal/raft/message/command.go @@ -0,0 +1,66 @@ +package message + +import "github.com/tomarrell/lbadd/internal/compiler/command" + +var _ Message = (*Command)(nil) +var _ command.Command = (*Command)(nil) + +// NewCommand creates a new Command variable. +func NewCommand() *Command { + return &Command{} +} + +// Kind returns KindCommand. +func (*Command) Kind() Kind { + return KindCommand +} + +// Kind returns KindExpr +func (*Expr) Kind() Kind { + return KindExpr +} + +// Kind returns KindCommandScan. +func (*Command_Scan) Kind() Kind { + return KindCommandScan +} + +// Kind returns KindCommandSelect. +func (*Command_Select) Kind() Kind { + return KindCommandSelect +} + +// Kind returns KindCommandProject. +func (*Command_Project) Kind() Kind { + return KindCommandProject +} + +// Kind returns KindCommandDelete. +func (*Command_Delete) Kind() Kind { + return KindCommandDelete +} + +// Kind returns KindCommandUpdate. +func (*Command_Update) Kind() Kind { + return KindCommandUpdate +} + +// Kind returns KindCommandDrop. +func (*CommandDrop) Kind() Kind { + return KindCommandDrop +} + +// Kind returns KindCommandLimit. +func (*Command_Limit) Kind() Kind { + return KindCommandLimit +} + +// Kind returns KindCommandJoin. +func (*Command_Join) Kind() Kind { + return KindCommandJoin +} + +// Kind returns KindCommandInsert. +func (*Command_Insert) Kind() Kind { + return KindCommandInsert +} diff --git a/internal/raft/message/command.pb.go b/internal/raft/message/command.pb.go new file mode 100644 index 00000000..d22edb83 --- /dev/null +++ b/internal/raft/message/command.pb.go @@ -0,0 +1,2866 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: command.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type JoinType int32 + +const ( + JoinType_JoinUnknown JoinType = 0 + JoinType_JoinLeft JoinType = 1 + JoinType_JoinLeftOuter JoinType = 2 + JoinType_JoinInner JoinType = 3 + JoinType_JoinCross JoinType = 4 +) + +// Enum value maps for JoinType. +var ( + JoinType_name = map[int32]string{ + 0: "JoinUnknown", + 1: "JoinLeft", + 2: "JoinLeftOuter", + 3: "JoinInner", + 4: "JoinCross", + } + JoinType_value = map[string]int32{ + "JoinUnknown": 0, + "JoinLeft": 1, + "JoinLeftOuter": 2, + "JoinInner": 3, + "JoinCross": 4, + } +) + +func (x JoinType) Enum() *JoinType { + p := new(JoinType) + *p = x + return p +} + +func (x JoinType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (JoinType) Descriptor() protoreflect.EnumDescriptor { + return file_command_proto_enumTypes[0].Descriptor() +} + +func (JoinType) Type() protoreflect.EnumType { + return &file_command_proto_enumTypes[0] +} + +func (x JoinType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use JoinType.Descriptor instead. +func (JoinType) EnumDescriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{0} +} + +type UpdateOr int32 + +const ( + UpdateOr_UpdateOrUnknown UpdateOr = 0 + UpdateOr_UpdateOrRollback UpdateOr = 1 + UpdateOr_UpdateOrAbort UpdateOr = 2 + UpdateOr_UpdateOrReplace UpdateOr = 3 + UpdateOr_UpdateOrFail UpdateOr = 4 + UpdateOr_UpdateOrIgnore UpdateOr = 5 +) + +// Enum value maps for UpdateOr. +var ( + UpdateOr_name = map[int32]string{ + 0: "UpdateOrUnknown", + 1: "UpdateOrRollback", + 2: "UpdateOrAbort", + 3: "UpdateOrReplace", + 4: "UpdateOrFail", + 5: "UpdateOrIgnore", + } + UpdateOr_value = map[string]int32{ + "UpdateOrUnknown": 0, + "UpdateOrRollback": 1, + "UpdateOrAbort": 2, + "UpdateOrReplace": 3, + "UpdateOrFail": 4, + "UpdateOrIgnore": 5, + } +) + +func (x UpdateOr) Enum() *UpdateOr { + p := new(UpdateOr) + *p = x + return p +} + +func (x UpdateOr) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (UpdateOr) Descriptor() protoreflect.EnumDescriptor { + return file_command_proto_enumTypes[1].Descriptor() +} + +func (UpdateOr) Type() protoreflect.EnumType { + return &file_command_proto_enumTypes[1] +} + +func (x UpdateOr) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use UpdateOr.Descriptor instead. +func (UpdateOr) EnumDescriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{1} +} + +type InsertOr int32 + +const ( + InsertOr_InsertOrUnknown InsertOr = 0 + InsertOr_InsertOrReplace InsertOr = 1 + InsertOr_InsertOrRollback InsertOr = 2 + InsertOr_InsertOrAbort InsertOr = 3 + InsertOr_InsertOrFail InsertOr = 4 + InsertOr_InsertOrIgnore InsertOr = 5 +) + +// Enum value maps for InsertOr. +var ( + InsertOr_name = map[int32]string{ + 0: "InsertOrUnknown", + 1: "InsertOrReplace", + 2: "InsertOrRollback", + 3: "InsertOrAbort", + 4: "InsertOrFail", + 5: "InsertOrIgnore", + } + InsertOr_value = map[string]int32{ + "InsertOrUnknown": 0, + "InsertOrReplace": 1, + "InsertOrRollback": 2, + "InsertOrAbort": 3, + "InsertOrFail": 4, + "InsertOrIgnore": 5, + } +) + +func (x InsertOr) Enum() *InsertOr { + p := new(InsertOr) + *p = x + return p +} + +func (x InsertOr) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (InsertOr) Descriptor() protoreflect.EnumDescriptor { + return file_command_proto_enumTypes[2].Descriptor() +} + +func (InsertOr) Type() protoreflect.EnumType { + return &file_command_proto_enumTypes[2] +} + +func (x InsertOr) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use InsertOr.Descriptor instead. +func (InsertOr) EnumDescriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{2} +} + +type DropTarget int32 + +const ( + DropTarget_Table DropTarget = 0 + DropTarget_View DropTarget = 1 + DropTarget_Index DropTarget = 2 + DropTarget_Trigger DropTarget = 3 +) + +// Enum value maps for DropTarget. +var ( + DropTarget_name = map[int32]string{ + 0: "Table", + 1: "View", + 2: "Index", + 3: "Trigger", + } + DropTarget_value = map[string]int32{ + "Table": 0, + "View": 1, + "Index": 2, + "Trigger": 3, + } +) + +func (x DropTarget) Enum() *DropTarget { + p := new(DropTarget) + *p = x + return p +} + +func (x DropTarget) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DropTarget) Descriptor() protoreflect.EnumDescriptor { + return file_command_proto_enumTypes[3].Descriptor() +} + +func (DropTarget) Type() protoreflect.EnumType { + return &file_command_proto_enumTypes[3] +} + +func (x DropTarget) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DropTarget.Descriptor instead. +func (DropTarget) EnumDescriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{3} +} + +type SimpleTable struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Schema string `protobuf:"bytes,1,opt,name=Schema,proto3" json:"Schema,omitempty"` + Table string `protobuf:"bytes,2,opt,name=Table,proto3" json:"Table,omitempty"` + Alias string `protobuf:"bytes,3,opt,name=Alias,proto3" json:"Alias,omitempty"` + Indexed bool `protobuf:"varint,4,opt,name=Indexed,proto3" json:"Indexed,omitempty"` + Index string `protobuf:"bytes,5,opt,name=Index,proto3" json:"Index,omitempty"` +} + +func (x *SimpleTable) Reset() { + *x = SimpleTable{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SimpleTable) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SimpleTable) ProtoMessage() {} + +func (x *SimpleTable) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SimpleTable.ProtoReflect.Descriptor instead. +func (*SimpleTable) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{0} +} + +func (x *SimpleTable) GetSchema() string { + if x != nil { + return x.Schema + } + return "" +} + +func (x *SimpleTable) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + +func (x *SimpleTable) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +func (x *SimpleTable) GetIndexed() bool { + if x != nil { + return x.Indexed + } + return false +} + +func (x *SimpleTable) GetIndex() string { + if x != nil { + return x.Index + } + return "" +} + +type UpdateSetter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cols []string `protobuf:"bytes,1,rep,name=Cols,proto3" json:"Cols,omitempty"` + // Types that are assignable to Value: + // *UpdateSetter_Literal + // *UpdateSetter_Constant + // *UpdateSetter_Unary + // *UpdateSetter_Binary + // *UpdateSetter_Func + // *UpdateSetter_Equality + // *UpdateSetter_Range + Value isUpdateSetter_Value `protobuf_oneof:"Value"` +} + +func (x *UpdateSetter) Reset() { + *x = UpdateSetter{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateSetter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateSetter) ProtoMessage() {} + +func (x *UpdateSetter) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateSetter.ProtoReflect.Descriptor instead. +func (*UpdateSetter) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{1} +} + +func (x *UpdateSetter) GetCols() []string { + if x != nil { + return x.Cols + } + return nil +} + +func (m *UpdateSetter) GetValue() isUpdateSetter_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *UpdateSetter) GetLiteral() *LiteralExpr { + if x, ok := x.GetValue().(*UpdateSetter_Literal); ok { + return x.Literal + } + return nil +} + +func (x *UpdateSetter) GetConstant() *ConstantBooleanExpr { + if x, ok := x.GetValue().(*UpdateSetter_Constant); ok { + return x.Constant + } + return nil +} + +func (x *UpdateSetter) GetUnary() *UnaryExpr { + if x, ok := x.GetValue().(*UpdateSetter_Unary); ok { + return x.Unary + } + return nil +} + +func (x *UpdateSetter) GetBinary() *BinaryExpr { + if x, ok := x.GetValue().(*UpdateSetter_Binary); ok { + return x.Binary + } + return nil +} + +func (x *UpdateSetter) GetFunc() *FunctionExpr { + if x, ok := x.GetValue().(*UpdateSetter_Func); ok { + return x.Func + } + return nil +} + +func (x *UpdateSetter) GetEquality() *EqualityExpr { + if x, ok := x.GetValue().(*UpdateSetter_Equality); ok { + return x.Equality + } + return nil +} + +func (x *UpdateSetter) GetRange() *RangeExpr { + if x, ok := x.GetValue().(*UpdateSetter_Range); ok { + return x.Range + } + return nil +} + +type isUpdateSetter_Value interface { + isUpdateSetter_Value() +} + +type UpdateSetter_Literal struct { + Literal *LiteralExpr `protobuf:"bytes,2,opt,name=literal,proto3,oneof"` +} + +type UpdateSetter_Constant struct { + Constant *ConstantBooleanExpr `protobuf:"bytes,3,opt,name=constant,proto3,oneof"` +} + +type UpdateSetter_Unary struct { + Unary *UnaryExpr `protobuf:"bytes,4,opt,name=unary,proto3,oneof"` +} + +type UpdateSetter_Binary struct { + Binary *BinaryExpr `protobuf:"bytes,5,opt,name=binary,proto3,oneof"` +} + +type UpdateSetter_Func struct { + Func *FunctionExpr `protobuf:"bytes,6,opt,name=func,proto3,oneof"` +} + +type UpdateSetter_Equality struct { + Equality *EqualityExpr `protobuf:"bytes,7,opt,name=equality,proto3,oneof"` +} + +type UpdateSetter_Range struct { + Range *RangeExpr `protobuf:"bytes,8,opt,name=range,proto3,oneof"` +} + +func (*UpdateSetter_Literal) isUpdateSetter_Value() {} + +func (*UpdateSetter_Constant) isUpdateSetter_Value() {} + +func (*UpdateSetter_Unary) isUpdateSetter_Value() {} + +func (*UpdateSetter_Binary) isUpdateSetter_Value() {} + +func (*UpdateSetter_Func) isUpdateSetter_Value() {} + +func (*UpdateSetter_Equality) isUpdateSetter_Value() {} + +func (*UpdateSetter_Range) isUpdateSetter_Value() {} + +type Column struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table string `protobuf:"bytes,1,opt,name=Table,proto3" json:"Table,omitempty"` + Column *Expr `protobuf:"bytes,2,opt,name=Column,proto3" json:"Column,omitempty"` + Alias string `protobuf:"bytes,3,opt,name=Alias,proto3" json:"Alias,omitempty"` +} + +func (x *Column) Reset() { + *x = Column{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Column) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Column) ProtoMessage() {} + +func (x *Column) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Column.ProtoReflect.Descriptor instead. +func (*Column) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{2} +} + +func (x *Column) GetTable() string { + if x != nil { + return x.Table + } + return "" +} + +func (x *Column) GetColumn() *Expr { + if x != nil { + return x.Column + } + return nil +} + +func (x *Column) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +type List struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to List: + // *List_Scan + // *List_Select + // *List_Project + // *List_Join + // *List_Limit + // *List_Offset + // *List_Distinct + // *List_Values + List isList_List `protobuf_oneof:"list"` +} + +func (x *List) Reset() { + *x = List{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *List) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*List) ProtoMessage() {} + +func (x *List) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use List.ProtoReflect.Descriptor instead. +func (*List) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{3} +} + +func (m *List) GetList() isList_List { + if m != nil { + return m.List + } + return nil +} + +func (x *List) GetScan() *Command_Scan { + if x, ok := x.GetList().(*List_Scan); ok { + return x.Scan + } + return nil +} + +func (x *List) GetSelect() *Command_Select { + if x, ok := x.GetList().(*List_Select); ok { + return x.Select + } + return nil +} + +func (x *List) GetProject() *Command_Project { + if x, ok := x.GetList().(*List_Project); ok { + return x.Project + } + return nil +} + +func (x *List) GetJoin() *Command_Join { + if x, ok := x.GetList().(*List_Join); ok { + return x.Join + } + return nil +} + +func (x *List) GetLimit() *Command_Limit { + if x, ok := x.GetList().(*List_Limit); ok { + return x.Limit + } + return nil +} + +func (x *List) GetOffset() *Command_Offset { + if x, ok := x.GetList().(*List_Offset); ok { + return x.Offset + } + return nil +} + +func (x *List) GetDistinct() *Command_Distinct { + if x, ok := x.GetList().(*List_Distinct); ok { + return x.Distinct + } + return nil +} + +func (x *List) GetValues() *Command_Values { + if x, ok := x.GetList().(*List_Values); ok { + return x.Values + } + return nil +} + +type isList_List interface { + isList_List() +} + +type List_Scan struct { + Scan *Command_Scan `protobuf:"bytes,1,opt,name=scan,proto3,oneof"` +} + +type List_Select struct { + Select *Command_Select `protobuf:"bytes,2,opt,name=select,proto3,oneof"` +} + +type List_Project struct { + Project *Command_Project `protobuf:"bytes,3,opt,name=project,proto3,oneof"` +} + +type List_Join struct { + Join *Command_Join `protobuf:"bytes,4,opt,name=join,proto3,oneof"` +} + +type List_Limit struct { + Limit *Command_Limit `protobuf:"bytes,5,opt,name=limit,proto3,oneof"` +} + +type List_Offset struct { + Offset *Command_Offset `protobuf:"bytes,6,opt,name=offset,proto3,oneof"` +} + +type List_Distinct struct { + Distinct *Command_Distinct `protobuf:"bytes,7,opt,name=distinct,proto3,oneof"` +} + +type List_Values struct { + Values *Command_Values `protobuf:"bytes,8,opt,name=values,proto3,oneof"` +} + +func (*List_Scan) isList_List() {} + +func (*List_Select) isList_List() {} + +func (*List_Project) isList_List() {} + +func (*List_Join) isList_List() {} + +func (*List_Limit) isList_List() {} + +func (*List_Offset) isList_List() {} + +func (*List_Distinct) isList_List() {} + +func (*List_Values) isList_List() {} + +type Command struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Command) Reset() { + *x = Command{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command) ProtoMessage() {} + +func (x *Command) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command.ProtoReflect.Descriptor instead. +func (*Command) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4} +} + +type Expr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Expr: + // *Expr_Literal + // *Expr_Constant + // *Expr_Unary + // *Expr_Binary + // *Expr_Func + // *Expr_Equality + // *Expr_Range + Expr isExpr_Expr `protobuf_oneof:"expr"` +} + +func (x *Expr) Reset() { + *x = Expr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Expr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Expr) ProtoMessage() {} + +func (x *Expr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Expr.ProtoReflect.Descriptor instead. +func (*Expr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{5} +} + +func (m *Expr) GetExpr() isExpr_Expr { + if m != nil { + return m.Expr + } + return nil +} + +func (x *Expr) GetLiteral() *LiteralExpr { + if x, ok := x.GetExpr().(*Expr_Literal); ok { + return x.Literal + } + return nil +} + +func (x *Expr) GetConstant() *ConstantBooleanExpr { + if x, ok := x.GetExpr().(*Expr_Constant); ok { + return x.Constant + } + return nil +} + +func (x *Expr) GetUnary() *UnaryExpr { + if x, ok := x.GetExpr().(*Expr_Unary); ok { + return x.Unary + } + return nil +} + +func (x *Expr) GetBinary() *BinaryExpr { + if x, ok := x.GetExpr().(*Expr_Binary); ok { + return x.Binary + } + return nil +} + +func (x *Expr) GetFunc() *FunctionExpr { + if x, ok := x.GetExpr().(*Expr_Func); ok { + return x.Func + } + return nil +} + +func (x *Expr) GetEquality() *EqualityExpr { + if x, ok := x.GetExpr().(*Expr_Equality); ok { + return x.Equality + } + return nil +} + +func (x *Expr) GetRange() *RangeExpr { + if x, ok := x.GetExpr().(*Expr_Range); ok { + return x.Range + } + return nil +} + +type isExpr_Expr interface { + isExpr_Expr() +} + +type Expr_Literal struct { + Literal *LiteralExpr `protobuf:"bytes,1,opt,name=literal,proto3,oneof"` +} + +type Expr_Constant struct { + Constant *ConstantBooleanExpr `protobuf:"bytes,2,opt,name=constant,proto3,oneof"` +} + +type Expr_Unary struct { + Unary *UnaryExpr `protobuf:"bytes,3,opt,name=unary,proto3,oneof"` +} + +type Expr_Binary struct { + Binary *BinaryExpr `protobuf:"bytes,4,opt,name=binary,proto3,oneof"` +} + +type Expr_Func struct { + Func *FunctionExpr `protobuf:"bytes,5,opt,name=func,proto3,oneof"` +} + +type Expr_Equality struct { + Equality *EqualityExpr `protobuf:"bytes,6,opt,name=equality,proto3,oneof"` +} + +type Expr_Range struct { + Range *RangeExpr `protobuf:"bytes,7,opt,name=range,proto3,oneof"` +} + +func (*Expr_Literal) isExpr_Expr() {} + +func (*Expr_Constant) isExpr_Expr() {} + +func (*Expr_Unary) isExpr_Expr() {} + +func (*Expr_Binary) isExpr_Expr() {} + +func (*Expr_Func) isExpr_Expr() {} + +func (*Expr_Equality) isExpr_Expr() {} + +func (*Expr_Range) isExpr_Expr() {} + +type RepeatedExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Expr []*Expr `protobuf:"bytes,1,rep,name=expr,proto3" json:"expr,omitempty"` +} + +func (x *RepeatedExpr) Reset() { + *x = RepeatedExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepeatedExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepeatedExpr) ProtoMessage() {} + +func (x *RepeatedExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepeatedExpr.ProtoReflect.Descriptor instead. +func (*RepeatedExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{6} +} + +func (x *RepeatedExpr) GetExpr() []*Expr { + if x != nil { + return x.Expr + } + return nil +} + +type LiteralExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value string `protobuf:"bytes,1,opt,name=Value,proto3" json:"Value,omitempty"` +} + +func (x *LiteralExpr) Reset() { + *x = LiteralExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LiteralExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LiteralExpr) ProtoMessage() {} + +func (x *LiteralExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LiteralExpr.ProtoReflect.Descriptor instead. +func (*LiteralExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{7} +} + +func (x *LiteralExpr) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type ConstantBooleanExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Value bool `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"` +} + +func (x *ConstantBooleanExpr) Reset() { + *x = ConstantBooleanExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ConstantBooleanExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConstantBooleanExpr) ProtoMessage() {} + +func (x *ConstantBooleanExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConstantBooleanExpr.ProtoReflect.Descriptor instead. +func (*ConstantBooleanExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{8} +} + +func (x *ConstantBooleanExpr) GetValue() bool { + if x != nil { + return x.Value + } + return false +} + +type UnaryExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Operator string `protobuf:"bytes,1,opt,name=Operator,proto3" json:"Operator,omitempty"` + Value *Expr `protobuf:"bytes,2,opt,name=Value,proto3" json:"Value,omitempty"` +} + +func (x *UnaryExpr) Reset() { + *x = UnaryExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UnaryExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnaryExpr) ProtoMessage() {} + +func (x *UnaryExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnaryExpr.ProtoReflect.Descriptor instead. +func (*UnaryExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{9} +} + +func (x *UnaryExpr) GetOperator() string { + if x != nil { + return x.Operator + } + return "" +} + +func (x *UnaryExpr) GetValue() *Expr { + if x != nil { + return x.Value + } + return nil +} + +type BinaryExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Operator string `protobuf:"bytes,1,opt,name=Operator,proto3" json:"Operator,omitempty"` + Left *Expr `protobuf:"bytes,2,opt,name=Left,proto3" json:"Left,omitempty"` + Right *Expr `protobuf:"bytes,3,opt,name=Right,proto3" json:"Right,omitempty"` +} + +func (x *BinaryExpr) Reset() { + *x = BinaryExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BinaryExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BinaryExpr) ProtoMessage() {} + +func (x *BinaryExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BinaryExpr.ProtoReflect.Descriptor instead. +func (*BinaryExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{10} +} + +func (x *BinaryExpr) GetOperator() string { + if x != nil { + return x.Operator + } + return "" +} + +func (x *BinaryExpr) GetLeft() *Expr { + if x != nil { + return x.Left + } + return nil +} + +func (x *BinaryExpr) GetRight() *Expr { + if x != nil { + return x.Right + } + return nil +} + +type FunctionExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Distinct bool `protobuf:"varint,2,opt,name=Distinct,proto3" json:"Distinct,omitempty"` + Args []*Expr `protobuf:"bytes,3,rep,name=Args,proto3" json:"Args,omitempty"` +} + +func (x *FunctionExpr) Reset() { + *x = FunctionExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FunctionExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FunctionExpr) ProtoMessage() {} + +func (x *FunctionExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FunctionExpr.ProtoReflect.Descriptor instead. +func (*FunctionExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{11} +} + +func (x *FunctionExpr) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *FunctionExpr) GetDistinct() bool { + if x != nil { + return x.Distinct + } + return false +} + +func (x *FunctionExpr) GetArgs() []*Expr { + if x != nil { + return x.Args + } + return nil +} + +type EqualityExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Left *Expr `protobuf:"bytes,1,opt,name=Left,proto3" json:"Left,omitempty"` + Right *Expr `protobuf:"bytes,2,opt,name=Right,proto3" json:"Right,omitempty"` + Invert bool `protobuf:"varint,3,opt,name=Invert,proto3" json:"Invert,omitempty"` +} + +func (x *EqualityExpr) Reset() { + *x = EqualityExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EqualityExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EqualityExpr) ProtoMessage() {} + +func (x *EqualityExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EqualityExpr.ProtoReflect.Descriptor instead. +func (*EqualityExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{12} +} + +func (x *EqualityExpr) GetLeft() *Expr { + if x != nil { + return x.Left + } + return nil +} + +func (x *EqualityExpr) GetRight() *Expr { + if x != nil { + return x.Right + } + return nil +} + +func (x *EqualityExpr) GetInvert() bool { + if x != nil { + return x.Invert + } + return false +} + +type RangeExpr struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Needle *Expr `protobuf:"bytes,1,opt,name=Needle,proto3" json:"Needle,omitempty"` + Lo *Expr `protobuf:"bytes,2,opt,name=Lo,proto3" json:"Lo,omitempty"` + Hi *Expr `protobuf:"bytes,3,opt,name=Hi,proto3" json:"Hi,omitempty"` + Invert bool `protobuf:"varint,4,opt,name=Invert,proto3" json:"Invert,omitempty"` +} + +func (x *RangeExpr) Reset() { + *x = RangeExpr{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RangeExpr) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RangeExpr) ProtoMessage() {} + +func (x *RangeExpr) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RangeExpr.ProtoReflect.Descriptor instead. +func (*RangeExpr) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{13} +} + +func (x *RangeExpr) GetNeedle() *Expr { + if x != nil { + return x.Needle + } + return nil +} + +func (x *RangeExpr) GetLo() *Expr { + if x != nil { + return x.Lo + } + return nil +} + +func (x *RangeExpr) GetHi() *Expr { + if x != nil { + return x.Hi + } + return nil +} + +func (x *RangeExpr) GetInvert() bool { + if x != nil { + return x.Invert + } + return false +} + +type Command_Scan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table *SimpleTable `protobuf:"bytes,1,opt,name=Table,proto3" json:"Table,omitempty"` +} + +func (x *Command_Scan) Reset() { + *x = Command_Scan{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Scan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Scan) ProtoMessage() {} + +func (x *Command_Scan) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Scan.ProtoReflect.Descriptor instead. +func (*Command_Scan) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *Command_Scan) GetTable() *SimpleTable { + if x != nil { + return x.Table + } + return nil +} + +type Command_Select struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter *Expr `protobuf:"bytes,1,opt,name=Filter,proto3" json:"Filter,omitempty"` + Input *List `protobuf:"bytes,2,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Select) Reset() { + *x = Command_Select{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Select) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Select) ProtoMessage() {} + +func (x *Command_Select) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Select.ProtoReflect.Descriptor instead. +func (*Command_Select) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *Command_Select) GetFilter() *Expr { + if x != nil { + return x.Filter + } + return nil +} + +func (x *Command_Select) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +type Command_Project struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cols []*Column `protobuf:"bytes,1,rep,name=Cols,proto3" json:"Cols,omitempty"` + Input *List `protobuf:"bytes,2,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Project) Reset() { + *x = Command_Project{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Project) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Project) ProtoMessage() {} + +func (x *Command_Project) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Project.ProtoReflect.Descriptor instead. +func (*Command_Project) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 2} +} + +func (x *Command_Project) GetCols() []*Column { + if x != nil { + return x.Cols + } + return nil +} + +func (x *Command_Project) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +type Command_Delete struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Table *SimpleTable `protobuf:"bytes,1,opt,name=Table,proto3" json:"Table,omitempty"` + Filter *Expr `protobuf:"bytes,2,opt,name=Filter,proto3" json:"Filter,omitempty"` +} + +func (x *Command_Delete) Reset() { + *x = Command_Delete{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Delete) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Delete) ProtoMessage() {} + +func (x *Command_Delete) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Delete.ProtoReflect.Descriptor instead. +func (*Command_Delete) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 3} +} + +func (x *Command_Delete) GetTable() *SimpleTable { + if x != nil { + return x.Table + } + return nil +} + +func (x *Command_Delete) GetFilter() *Expr { + if x != nil { + return x.Filter + } + return nil +} + +type CommandDrop struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Target DropTarget `protobuf:"varint,1,opt,name=target,proto3,enum=message.DropTarget" json:"target,omitempty"` + IfExists bool `protobuf:"varint,2,opt,name=IfExists,proto3" json:"IfExists,omitempty"` + Schema string `protobuf:"bytes,3,opt,name=Schema,proto3" json:"Schema,omitempty"` + Name string `protobuf:"bytes,4,opt,name=Name,proto3" json:"Name,omitempty"` +} + +func (x *CommandDrop) Reset() { + *x = CommandDrop{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommandDrop) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommandDrop) ProtoMessage() {} + +func (x *CommandDrop) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommandDrop.ProtoReflect.Descriptor instead. +func (*CommandDrop) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 4} +} + +func (x *CommandDrop) GetTarget() DropTarget { + if x != nil { + return x.Target + } + return DropTarget_Table +} + +func (x *CommandDrop) GetIfExists() bool { + if x != nil { + return x.IfExists + } + return false +} + +func (x *CommandDrop) GetSchema() string { + if x != nil { + return x.Schema + } + return "" +} + +func (x *CommandDrop) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type Command_Update struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UpdateOr UpdateOr `protobuf:"varint,1,opt,name=UpdateOr,proto3,enum=message.UpdateOr" json:"UpdateOr,omitempty"` + Table *SimpleTable `protobuf:"bytes,2,opt,name=Table,proto3" json:"Table,omitempty"` + Updates []*UpdateSetter `protobuf:"bytes,3,rep,name=Updates,proto3" json:"Updates,omitempty"` + Filter *Expr `protobuf:"bytes,4,opt,name=Filter,proto3" json:"Filter,omitempty"` +} + +func (x *Command_Update) Reset() { + *x = Command_Update{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Update) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Update) ProtoMessage() {} + +func (x *Command_Update) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Update.ProtoReflect.Descriptor instead. +func (*Command_Update) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 5} +} + +func (x *Command_Update) GetUpdateOr() UpdateOr { + if x != nil { + return x.UpdateOr + } + return UpdateOr_UpdateOrUnknown +} + +func (x *Command_Update) GetTable() *SimpleTable { + if x != nil { + return x.Table + } + return nil +} + +func (x *Command_Update) GetUpdates() []*UpdateSetter { + if x != nil { + return x.Updates + } + return nil +} + +func (x *Command_Update) GetFilter() *Expr { + if x != nil { + return x.Filter + } + return nil +} + +type Command_Join struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Natural bool `protobuf:"varint,1,opt,name=Natural,proto3" json:"Natural,omitempty"` + Type JoinType `protobuf:"varint,2,opt,name=Type,proto3,enum=message.JoinType" json:"Type,omitempty"` + Filter *Expr `protobuf:"bytes,3,opt,name=Filter,proto3" json:"Filter,omitempty"` + Left *List `protobuf:"bytes,4,opt,name=Left,proto3" json:"Left,omitempty"` + Right *List `protobuf:"bytes,5,opt,name=Right,proto3" json:"Right,omitempty"` +} + +func (x *Command_Join) Reset() { + *x = Command_Join{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Join) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Join) ProtoMessage() {} + +func (x *Command_Join) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Join.ProtoReflect.Descriptor instead. +func (*Command_Join) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 6} +} + +func (x *Command_Join) GetNatural() bool { + if x != nil { + return x.Natural + } + return false +} + +func (x *Command_Join) GetType() JoinType { + if x != nil { + return x.Type + } + return JoinType_JoinUnknown +} + +func (x *Command_Join) GetFilter() *Expr { + if x != nil { + return x.Filter + } + return nil +} + +func (x *Command_Join) GetLeft() *List { + if x != nil { + return x.Left + } + return nil +} + +func (x *Command_Join) GetRight() *List { + if x != nil { + return x.Right + } + return nil +} + +type Command_Limit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Limit *Expr `protobuf:"bytes,1,opt,name=Limit,proto3" json:"Limit,omitempty"` + Input *List `protobuf:"bytes,2,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Limit) Reset() { + *x = Command_Limit{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Limit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Limit) ProtoMessage() {} + +func (x *Command_Limit) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Limit.ProtoReflect.Descriptor instead. +func (*Command_Limit) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 7} +} + +func (x *Command_Limit) GetLimit() *Expr { + if x != nil { + return x.Limit + } + return nil +} + +func (x *Command_Limit) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +type Command_Offset struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Offset *Expr `protobuf:"bytes,1,opt,name=Offset,proto3" json:"Offset,omitempty"` + Input *List `protobuf:"bytes,2,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Offset) Reset() { + *x = Command_Offset{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Offset) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Offset) ProtoMessage() {} + +func (x *Command_Offset) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Offset.ProtoReflect.Descriptor instead. +func (*Command_Offset) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 8} +} + +func (x *Command_Offset) GetOffset() *Expr { + if x != nil { + return x.Offset + } + return nil +} + +func (x *Command_Offset) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +type Command_Empty struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cols []*Column `protobuf:"bytes,1,rep,name=Cols,proto3" json:"Cols,omitempty"` +} + +func (x *Command_Empty) Reset() { + *x = Command_Empty{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Empty) ProtoMessage() {} + +func (x *Command_Empty) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Empty.ProtoReflect.Descriptor instead. +func (*Command_Empty) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 9} +} + +func (x *Command_Empty) GetCols() []*Column { + if x != nil { + return x.Cols + } + return nil +} + +type Command_Distinct struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Input *List `protobuf:"bytes,1,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Distinct) Reset() { + *x = Command_Distinct{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Distinct) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Distinct) ProtoMessage() {} + +func (x *Command_Distinct) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Distinct.ProtoReflect.Descriptor instead. +func (*Command_Distinct) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 10} +} + +func (x *Command_Distinct) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +type Command_Values struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Expr []*RepeatedExpr `protobuf:"bytes,1,rep,name=expr,proto3" json:"expr,omitempty"` +} + +func (x *Command_Values) Reset() { + *x = Command_Values{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Values) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Values) ProtoMessage() {} + +func (x *Command_Values) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Values.ProtoReflect.Descriptor instead. +func (*Command_Values) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 11} +} + +func (x *Command_Values) GetExpr() []*RepeatedExpr { + if x != nil { + return x.Expr + } + return nil +} + +type Command_Insert struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + InsertOr InsertOr `protobuf:"varint,1,opt,name=InsertOr,proto3,enum=message.InsertOr" json:"InsertOr,omitempty"` + Table *SimpleTable `protobuf:"bytes,2,opt,name=Table,proto3" json:"Table,omitempty"` + Cols []*Column `protobuf:"bytes,3,rep,name=Cols,proto3" json:"Cols,omitempty"` + DefaultValues bool `protobuf:"varint,4,opt,name=DefaultValues,proto3" json:"DefaultValues,omitempty"` + Input *List `protobuf:"bytes,5,opt,name=Input,proto3" json:"Input,omitempty"` +} + +func (x *Command_Insert) Reset() { + *x = Command_Insert{} + if protoimpl.UnsafeEnabled { + mi := &file_command_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command_Insert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command_Insert) ProtoMessage() {} + +func (x *Command_Insert) ProtoReflect() protoreflect.Message { + mi := &file_command_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command_Insert.ProtoReflect.Descriptor instead. +func (*Command_Insert) Descriptor() ([]byte, []int) { + return file_command_proto_rawDescGZIP(), []int{4, 12} +} + +func (x *Command_Insert) GetInsertOr() InsertOr { + if x != nil { + return x.InsertOr + } + return InsertOr_InsertOrUnknown +} + +func (x *Command_Insert) GetTable() *SimpleTable { + if x != nil { + return x.Table + } + return nil +} + +func (x *Command_Insert) GetCols() []*Column { + if x != nil { + return x.Cols + } + return nil +} + +func (x *Command_Insert) GetDefaultValues() bool { + if x != nil { + return x.DefaultValues + } + return false +} + +func (x *Command_Insert) GetInput() *List { + if x != nil { + return x.Input + } + return nil +} + +var File_command_proto protoreflect.FileDescriptor + +var file_command_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x81, 0x01, 0x0a, 0x0b, 0x53, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x12, 0x14, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x82, 0x03, 0x0a, + 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x74, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, + 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x43, 0x6f, 0x6c, + 0x73, 0x12, 0x30, 0x0a, 0x07, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x74, + 0x65, 0x72, 0x61, 0x6c, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x69, 0x74, 0x65, + 0x72, 0x61, 0x6c, 0x12, 0x3a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x45, + 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x12, + 0x2a, 0x0a, 0x05, 0x75, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, + 0x70, 0x72, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x62, + 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, 0x70, 0x72, + 0x48, 0x00, 0x52, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x04, 0x66, 0x75, + 0x6e, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x72, 0x48, + 0x00, 0x52, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x12, 0x33, 0x0a, 0x08, 0x65, 0x71, 0x75, 0x61, 0x6c, + 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x78, 0x70, 0x72, + 0x48, 0x00, 0x52, 0x08, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x05, + 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x78, 0x70, 0x72, 0x48, + 0x00, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x07, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x5b, 0x0a, 0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x54, + 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x25, 0x0a, 0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, + 0x52, 0x06, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x22, 0xa0, + 0x03, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x73, 0x63, 0x61, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x63, 0x61, 0x6e, 0x48, 0x00, 0x52, 0x04, + 0x73, 0x63, 0x61, 0x6e, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, + 0x06, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x34, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x48, 0x00, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2b, 0x0a, + 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4a, 0x6f, + 0x69, 0x6e, 0x48, 0x00, 0x52, 0x04, 0x6a, 0x6f, 0x69, 0x6e, 0x12, 0x2e, 0x0a, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x6d, 0x69, + 0x74, 0x48, 0x00, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x31, 0x0a, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x48, 0x00, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x37, 0x0a, + 0x08, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x64, 0x69, + 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x12, 0x31, 0x0a, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x48, + 0x00, 0x52, 0x06, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x6c, 0x69, 0x73, + 0x74, 0x22, 0xcc, 0x0a, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x32, 0x0a, + 0x04, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x2a, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x54, 0x61, 0x62, 0x6c, + 0x65, 0x1a, 0x54, 0x0a, 0x06, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x12, 0x23, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x53, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x0f, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x52, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x12, 0x23, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x5b, 0x0a, 0x06, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x54, 0x61, 0x62, + 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, + 0x72, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x7b, 0x0a, 0x04, 0x64, 0x72, 0x6f, + 0x70, 0x12, 0x2b, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x44, 0x72, 0x6f, 0x70, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x49, 0x66, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x08, 0x49, 0x66, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0xbb, 0x01, 0x0a, 0x06, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x12, 0x2d, 0x0a, 0x08, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x52, 0x08, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, + 0x12, 0x2a, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, + 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x07, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, + 0x74, 0x74, 0x65, 0x72, 0x52, 0x07, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, + 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x06, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x1a, 0xb6, 0x01, 0x0a, 0x04, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x18, 0x0a, + 0x07, 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x4e, 0x61, 0x74, 0x75, 0x72, 0x61, 0x6c, 0x12, 0x25, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x25, + 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x06, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x4c, 0x65, 0x66, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x04, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x23, 0x0a, 0x05, 0x52, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x52, 0x69, 0x67, 0x68, 0x74, 0x1a, 0x51, 0x0a, + 0x05, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x05, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x45, 0x78, 0x70, 0x72, 0x52, 0x05, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x05, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x1a, 0x54, 0x0a, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x25, 0x0a, 0x06, 0x4f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x06, 0x4f, 0x66, 0x66, 0x73, 0x65, + 0x74, 0x12, 0x23, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x2c, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x23, 0x0a, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, 0x04, + 0x43, 0x6f, 0x6c, 0x73, 0x1a, 0x2f, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, + 0x12, 0x23, 0x0a, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x1a, 0x33, 0x0a, 0x06, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, + 0x29, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x45, 0x78, 0x70, 0x72, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x1a, 0xd3, 0x01, 0x0a, 0x06, 0x49, + 0x6e, 0x73, 0x65, 0x72, 0x74, 0x12, 0x2d, 0x0a, 0x08, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x52, 0x08, 0x49, 0x6e, 0x73, 0x65, + 0x72, 0x74, 0x4f, 0x72, 0x12, 0x2a, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x53, 0x69, + 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, + 0x12, 0x23, 0x0a, 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x52, + 0x04, 0x43, 0x6f, 0x6c, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x12, 0x23, 0x0a, 0x05, 0x49, + 0x6e, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x05, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x22, 0xe5, 0x02, 0x0a, 0x04, 0x45, 0x78, 0x70, 0x72, 0x12, 0x30, 0x0a, 0x07, 0x6c, 0x69, 0x74, + 0x65, 0x72, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x4c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x78, 0x70, 0x72, + 0x48, 0x00, 0x52, 0x07, 0x6c, 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x3a, 0x0a, 0x08, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, + 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x08, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x75, 0x6e, 0x61, 0x72, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x05, 0x75, 0x6e, + 0x61, 0x72, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x42, 0x69, + 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x06, 0x62, 0x69, 0x6e, 0x61, + 0x72, 0x79, 0x12, 0x2b, 0x0a, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x46, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x04, 0x66, 0x75, 0x6e, 0x63, 0x12, + 0x33, 0x0a, 0x08, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x71, 0x75, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x08, 0x65, 0x71, 0x75, 0x61, + 0x6c, 0x69, 0x74, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x45, 0x78, 0x70, 0x72, 0x48, 0x00, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, + 0x42, 0x06, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, 0x22, 0x31, 0x0a, 0x0c, 0x72, 0x65, 0x70, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x45, 0x78, 0x70, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x65, 0x78, 0x70, 0x72, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x04, 0x65, 0x78, 0x70, 0x72, 0x22, 0x23, 0x0a, 0x0b, 0x4c, + 0x69, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x45, 0x78, 0x70, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x22, 0x2b, 0x0a, 0x13, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x42, 0x6f, 0x6f, 0x6c, + 0x65, 0x61, 0x6e, 0x45, 0x78, 0x70, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x4c, 0x0a, + 0x09, 0x55, 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, 0x70, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x23, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, + 0x45, 0x78, 0x70, 0x72, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x70, 0x0a, 0x0a, 0x42, + 0x69, 0x6e, 0x61, 0x72, 0x79, 0x45, 0x78, 0x70, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x21, 0x0a, 0x04, 0x4c, 0x65, 0x66, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, + 0x70, 0x72, 0x52, 0x04, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x23, 0x0a, 0x05, 0x52, 0x69, 0x67, 0x68, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x05, 0x52, 0x69, 0x67, 0x68, 0x74, 0x22, 0x61, 0x0a, + 0x0c, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x72, 0x12, 0x12, 0x0a, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74, 0x12, 0x21, 0x0a, + 0x04, 0x41, 0x72, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x04, 0x41, 0x72, 0x67, 0x73, + 0x22, 0x6e, 0x0a, 0x0c, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x45, 0x78, 0x70, 0x72, + 0x12, 0x21, 0x0a, 0x04, 0x4c, 0x65, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x04, 0x4c, + 0x65, 0x66, 0x74, 0x12, 0x23, 0x0a, 0x05, 0x52, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, + 0x72, 0x52, 0x05, 0x52, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, + 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, + 0x22, 0x88, 0x01, 0x0a, 0x09, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x78, 0x70, 0x72, 0x12, 0x25, + 0x0a, 0x06, 0x4e, 0x65, 0x65, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, 0x06, 0x4e, + 0x65, 0x65, 0x64, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x02, 0x4c, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, + 0x52, 0x02, 0x4c, 0x6f, 0x12, 0x1d, 0x0a, 0x02, 0x48, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x72, 0x52, + 0x02, 0x48, 0x69, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2a, 0x5a, 0x0a, 0x08, 0x4a, + 0x6f, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4a, 0x6f, 0x69, 0x6e, 0x55, + 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, + 0x4c, 0x65, 0x66, 0x74, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x65, + 0x66, 0x74, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x6f, 0x69, + 0x6e, 0x49, 0x6e, 0x6e, 0x65, 0x72, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x6f, 0x69, 0x6e, + 0x43, 0x72, 0x6f, 0x73, 0x73, 0x10, 0x04, 0x2a, 0x83, 0x01, 0x0a, 0x08, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4f, 0x72, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, + 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4f, 0x72, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x10, 0x01, 0x12, + 0x11, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x41, 0x62, 0x6f, 0x72, 0x74, + 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x52, 0x65, + 0x70, 0x6c, 0x61, 0x63, 0x65, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4f, 0x72, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x10, 0x05, 0x2a, 0x83, 0x01, + 0x0a, 0x08, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x6e, + 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, + 0x13, 0x0a, 0x0f, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x61, + 0x63, 0x65, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, + 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x49, 0x6e, + 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x10, 0x03, 0x12, 0x10, 0x0a, + 0x0c, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x10, 0x04, 0x12, + 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x4f, 0x72, 0x49, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x10, 0x05, 0x2a, 0x39, 0x0a, 0x0a, 0x44, 0x72, 0x6f, 0x70, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, + 0x56, 0x69, 0x65, 0x77, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x10, + 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x10, 0x03, 0x42, 0x0b, + 0x5a, 0x09, 0x2e, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_command_proto_rawDescOnce sync.Once + file_command_proto_rawDescData = file_command_proto_rawDesc +) + +func file_command_proto_rawDescGZIP() []byte { + file_command_proto_rawDescOnce.Do(func() { + file_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_command_proto_rawDescData) + }) + return file_command_proto_rawDescData +} + +var file_command_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 27) +var file_command_proto_goTypes = []interface{}{ + (JoinType)(0), // 0: message.JoinType + (UpdateOr)(0), // 1: message.UpdateOr + (InsertOr)(0), // 2: message.InsertOr + (DropTarget)(0), // 3: message.DropTarget + (*SimpleTable)(nil), // 4: message.SimpleTable + (*UpdateSetter)(nil), // 5: message.UpdateSetter + (*Column)(nil), // 6: message.Column + (*List)(nil), // 7: message.List + (*Command)(nil), // 8: message.Command + (*Expr)(nil), // 9: message.Expr + (*RepeatedExpr)(nil), // 10: message.repeatedExpr + (*LiteralExpr)(nil), // 11: message.LiteralExpr + (*ConstantBooleanExpr)(nil), // 12: message.ConstantBooleanExpr + (*UnaryExpr)(nil), // 13: message.UnaryExpr + (*BinaryExpr)(nil), // 14: message.BinaryExpr + (*FunctionExpr)(nil), // 15: message.FunctionExpr + (*EqualityExpr)(nil), // 16: message.EqualityExpr + (*RangeExpr)(nil), // 17: message.RangeExpr + (*Command_Scan)(nil), // 18: message.Command.Scan + (*Command_Select)(nil), // 19: message.Command.Select + (*Command_Project)(nil), // 20: message.Command.Project + (*Command_Delete)(nil), // 21: message.Command.Delete + (*CommandDrop)(nil), // 22: message.Command.drop + (*Command_Update)(nil), // 23: message.Command.Update + (*Command_Join)(nil), // 24: message.Command.Join + (*Command_Limit)(nil), // 25: message.Command.Limit + (*Command_Offset)(nil), // 26: message.Command.Offset + (*Command_Empty)(nil), // 27: message.Command.Empty + (*Command_Distinct)(nil), // 28: message.Command.Distinct + (*Command_Values)(nil), // 29: message.Command.Values + (*Command_Insert)(nil), // 30: message.Command.Insert +} +var file_command_proto_depIdxs = []int32{ + 11, // 0: message.UpdateSetter.literal:type_name -> message.LiteralExpr + 12, // 1: message.UpdateSetter.constant:type_name -> message.ConstantBooleanExpr + 13, // 2: message.UpdateSetter.unary:type_name -> message.UnaryExpr + 14, // 3: message.UpdateSetter.binary:type_name -> message.BinaryExpr + 15, // 4: message.UpdateSetter.func:type_name -> message.FunctionExpr + 16, // 5: message.UpdateSetter.equality:type_name -> message.EqualityExpr + 17, // 6: message.UpdateSetter.range:type_name -> message.RangeExpr + 9, // 7: message.Column.Column:type_name -> message.Expr + 18, // 8: message.List.scan:type_name -> message.Command.Scan + 19, // 9: message.List.select:type_name -> message.Command.Select + 20, // 10: message.List.project:type_name -> message.Command.Project + 24, // 11: message.List.join:type_name -> message.Command.Join + 25, // 12: message.List.limit:type_name -> message.Command.Limit + 26, // 13: message.List.offset:type_name -> message.Command.Offset + 28, // 14: message.List.distinct:type_name -> message.Command.Distinct + 29, // 15: message.List.values:type_name -> message.Command.Values + 11, // 16: message.Expr.literal:type_name -> message.LiteralExpr + 12, // 17: message.Expr.constant:type_name -> message.ConstantBooleanExpr + 13, // 18: message.Expr.unary:type_name -> message.UnaryExpr + 14, // 19: message.Expr.binary:type_name -> message.BinaryExpr + 15, // 20: message.Expr.func:type_name -> message.FunctionExpr + 16, // 21: message.Expr.equality:type_name -> message.EqualityExpr + 17, // 22: message.Expr.range:type_name -> message.RangeExpr + 9, // 23: message.repeatedExpr.expr:type_name -> message.Expr + 9, // 24: message.UnaryExpr.Value:type_name -> message.Expr + 9, // 25: message.BinaryExpr.Left:type_name -> message.Expr + 9, // 26: message.BinaryExpr.Right:type_name -> message.Expr + 9, // 27: message.FunctionExpr.Args:type_name -> message.Expr + 9, // 28: message.EqualityExpr.Left:type_name -> message.Expr + 9, // 29: message.EqualityExpr.Right:type_name -> message.Expr + 9, // 30: message.RangeExpr.Needle:type_name -> message.Expr + 9, // 31: message.RangeExpr.Lo:type_name -> message.Expr + 9, // 32: message.RangeExpr.Hi:type_name -> message.Expr + 4, // 33: message.Command.Scan.Table:type_name -> message.SimpleTable + 9, // 34: message.Command.Select.Filter:type_name -> message.Expr + 7, // 35: message.Command.Select.Input:type_name -> message.List + 6, // 36: message.Command.Project.Cols:type_name -> message.Column + 7, // 37: message.Command.Project.Input:type_name -> message.List + 4, // 38: message.Command.Delete.Table:type_name -> message.SimpleTable + 9, // 39: message.Command.Delete.Filter:type_name -> message.Expr + 3, // 40: message.Command.drop.target:type_name -> message.DropTarget + 1, // 41: message.Command.Update.UpdateOr:type_name -> message.UpdateOr + 4, // 42: message.Command.Update.Table:type_name -> message.SimpleTable + 5, // 43: message.Command.Update.Updates:type_name -> message.UpdateSetter + 9, // 44: message.Command.Update.Filter:type_name -> message.Expr + 0, // 45: message.Command.Join.Type:type_name -> message.JoinType + 9, // 46: message.Command.Join.Filter:type_name -> message.Expr + 7, // 47: message.Command.Join.Left:type_name -> message.List + 7, // 48: message.Command.Join.Right:type_name -> message.List + 9, // 49: message.Command.Limit.Limit:type_name -> message.Expr + 7, // 50: message.Command.Limit.Input:type_name -> message.List + 9, // 51: message.Command.Offset.Offset:type_name -> message.Expr + 7, // 52: message.Command.Offset.Input:type_name -> message.List + 6, // 53: message.Command.Empty.Cols:type_name -> message.Column + 7, // 54: message.Command.Distinct.Input:type_name -> message.List + 10, // 55: message.Command.Values.expr:type_name -> message.repeatedExpr + 2, // 56: message.Command.Insert.InsertOr:type_name -> message.InsertOr + 4, // 57: message.Command.Insert.Table:type_name -> message.SimpleTable + 6, // 58: message.Command.Insert.Cols:type_name -> message.Column + 7, // 59: message.Command.Insert.Input:type_name -> message.List + 60, // [60:60] is the sub-list for method output_type + 60, // [60:60] is the sub-list for method input_type + 60, // [60:60] is the sub-list for extension type_name + 60, // [60:60] is the sub-list for extension extendee + 0, // [0:60] is the sub-list for field type_name +} + +func init() { file_command_proto_init() } +func file_command_proto_init() { + if File_command_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SimpleTable); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateSetter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Column); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*List); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Expr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepeatedExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LiteralExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ConstantBooleanExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UnaryExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BinaryExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FunctionExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EqualityExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RangeExpr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Scan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Select); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Project); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Delete); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommandDrop); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Update); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Join); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Limit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Offset); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Empty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Distinct); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Values); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_command_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command_Insert); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_command_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*UpdateSetter_Literal)(nil), + (*UpdateSetter_Constant)(nil), + (*UpdateSetter_Unary)(nil), + (*UpdateSetter_Binary)(nil), + (*UpdateSetter_Func)(nil), + (*UpdateSetter_Equality)(nil), + (*UpdateSetter_Range)(nil), + } + file_command_proto_msgTypes[3].OneofWrappers = []interface{}{ + (*List_Scan)(nil), + (*List_Select)(nil), + (*List_Project)(nil), + (*List_Join)(nil), + (*List_Limit)(nil), + (*List_Offset)(nil), + (*List_Distinct)(nil), + (*List_Values)(nil), + } + file_command_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*Expr_Literal)(nil), + (*Expr_Constant)(nil), + (*Expr_Unary)(nil), + (*Expr_Binary)(nil), + (*Expr_Func)(nil), + (*Expr_Equality)(nil), + (*Expr_Range)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_command_proto_rawDesc, + NumEnums: 4, + NumMessages: 27, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_command_proto_goTypes, + DependencyIndexes: file_command_proto_depIdxs, + EnumInfos: file_command_proto_enumTypes, + MessageInfos: file_command_proto_msgTypes, + }.Build() + File_command_proto = out.File + file_command_proto_rawDesc = nil + file_command_proto_goTypes = nil + file_command_proto_depIdxs = nil +} diff --git a/internal/raft/message/command.proto b/internal/raft/message/command.proto new file mode 100644 index 00000000..db513a93 --- /dev/null +++ b/internal/raft/message/command.proto @@ -0,0 +1,209 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; + +message SimpleTable { + string Schema = 1; + string Table = 2; + string Alias = 3; + bool Indexed = 4; + string Index = 5; +} + +message UpdateSetter { + repeated string Cols = 1; + oneof Value { + LiteralExpr literal = 2; + ConstantBooleanExpr constant = 3; + UnaryExpr unary = 4; + BinaryExpr binary = 5; + FunctionExpr func = 6; + EqualityExpr equality = 7; + RangeExpr range = 8; + } +} + +enum JoinType { + JoinUnknown = 0; + JoinLeft = 1; + JoinLeftOuter = 2; + JoinInner = 3; + JoinCross = 4; +} + +enum UpdateOr { + UpdateOrUnknown = 0; + UpdateOrRollback = 1; + UpdateOrAbort = 2; + UpdateOrReplace = 3; + UpdateOrFail = 4; + UpdateOrIgnore = 5; +} + +enum InsertOr { + InsertOrUnknown = 0; + InsertOrReplace = 1; + InsertOrRollback = 2; + InsertOrAbort = 3; + InsertOrFail = 4; + InsertOrIgnore = 5; +} + +message Column { + string Table = 1; + Expr Column = 2; + string Alias = 3; +} + + message List { + oneof list { + Command.Scan scan = 1; + Command.Select select = 2; + Command.Project project = 3; + Command.Join join = 4; + Command.Limit limit = 5; + Command.Offset offset = 6; + Command.Distinct distinct = 7; + Command.Values values = 8; + } +} + +enum DropTarget { + Table = 0; + View = 1; + Index = 2; + Trigger = 3; +} + +message Command { + + message Scan { + SimpleTable Table = 1; + } + + message Select { + Expr Filter = 1; + List Input = 2; + } + + message Project { + repeated Column Cols = 1; + List Input = 2; + } + + message Delete { + SimpleTable Table = 1; + Expr Filter = 2; + } + + message drop { + DropTarget target = 1; + bool IfExists = 2; + string Schema = 3; + string Name = 4; + } + + message Update { + UpdateOr UpdateOr = 1; + SimpleTable Table = 2; + repeated UpdateSetter Updates = 3; + Expr Filter = 4; + } + + message Join { + bool Natural = 1; + JoinType Type = 2; + Expr Filter = 3; + List Left = 4; + List Right = 5; + } + + message Limit { + Expr Limit = 1; + List Input = 2; + } + + message Offset { + Expr Offset = 1; + List Input = 2; + } + + message Empty { + repeated Column Cols = 1; + } + + message Distinct { + List Input = 1; + } + + message Values { + repeated repeatedExpr expr = 1; + } + + message Insert { + InsertOr InsertOr = 1; + SimpleTable Table = 2; + repeated Column Cols = 3; + bool DefaultValues = 4; + List Input = 5; + } +} + +// Expression + +message Expr { + oneof expr { + LiteralExpr literal = 1; + ConstantBooleanExpr constant = 2; + UnaryExpr unary = 3; + BinaryExpr binary = 4; + FunctionExpr func = 5; + EqualityExpr equality = 6; + RangeExpr range = 7; + } +} + +message repeatedExpr { + repeated Expr expr = 1; +} + +message LiteralExpr { + string Value = 1; +} + +message ConstantBooleanExpr { + bool Value = 1; +} + +message UnaryExpr { + string Operator = 1; + Expr Value = 2; +} + +message BinaryExpr { + string Operator = 1; + Expr Left = 2; + Expr Right = 3; +} + +message FunctionExpr { + string Name = 1; + bool Distinct = 2; + repeated Expr Args = 3; +} + +message EqualityExpr { + Expr Left = 1; + Expr Right = 2; + bool Invert = 3; +} + +message RangeExpr { + Expr Needle = 1; + Expr Lo = 2; + Expr Hi = 3; + bool Invert = 4; +} \ No newline at end of file diff --git a/internal/raft/message/convert.go b/internal/raft/message/convert.go new file mode 100644 index 00000000..21258cff --- /dev/null +++ b/internal/raft/message/convert.go @@ -0,0 +1,1379 @@ +package message + +import ( + "github.com/tomarrell/lbadd/internal/compiler/command" +) + +// ConvertCommandToMessage converts a command.Command to a message.Message. +func ConvertCommandToMessage(cmd command.Command) (Message, error) { + if cmd == nil { + return nil, nil + } + switch c := cmd.(type) { + case command.Scan: + return ConvertCommandScanToMessageScan(c) + case command.Select: + return ConvertCommandSelectToMessageSelect(c) + case command.Project: + return ConvertCommandProjectToMessageProject(c) + case command.Delete: + return ConvertCommandDeleteToMessageDelete(c) + case *command.DropIndex: + return ConvertCommandDropToMessageDrop(c) + case *command.DropTable: + return ConvertCommandDropToMessageDrop(c) + case *command.DropTrigger: + return ConvertCommandDropToMessageDrop(c) + case *command.DropView: + return ConvertCommandDropToMessageDrop(c) + case command.Update: + return ConvertCommandUpdateToMessageUpdate(c) + case command.Join: + return ConvertCommandJoinToMessageJoin(c) + case command.Limit: + return ConvertCommandLimitToMessageLimit(c) + case command.Insert: + return ConvertCommandInsertToMessageInsert(c) + } + return nil, ErrUnknownCommandKind +} + +// ConvertCommandTableToMessageTable converts a command.Table to a SimpleTable. +func ConvertCommandTableToMessageTable(cmd command.Table) (*SimpleTable, error) { + if cmd == nil { + //TODO + return nil, nil + } + return &SimpleTable{ + Schema: cmd.(*command.SimpleTable).Schema, + Table: cmd.(*command.SimpleTable).Table, + Alias: cmd.(*command.SimpleTable).Alias, + Indexed: cmd.(*command.SimpleTable).Indexed, + Index: cmd.(*command.SimpleTable).Index, + }, nil +} + +// ConvertCommandScanToMessageScan converts a Command type to a Command_Scan type. +func ConvertCommandScanToMessageScan(cmd command.Scan) (*Command_Scan, error) { + table, err := ConvertCommandTableToMessageTable(cmd.Table) + if err != nil { + return nil, err + } + return &Command_Scan{ + Table: table, + }, nil +} + +// ConvertCommandLiteralExprToMessageLiteralExpr converts a command.Expr to a message.Expr_Literal. +func ConvertCommandLiteralExprToMessageLiteralExpr(cmd command.LiteralExpr) (*Expr_Literal, error) { + return &Expr_Literal{ + &LiteralExpr{ + Value: cmd.Value, + }, + }, nil +} + +// ConvertCommandConstantBooleanExprToMessageConstantBooleanExpr converts a command.Expr to a message.Expr_Constant. +func ConvertCommandConstantBooleanExprToMessageConstantBooleanExpr(cmd command.ConstantBooleanExpr) (*Expr_Constant, error) { + return &Expr_Constant{ + &ConstantBooleanExpr{ + Value: cmd.Value, + }, + }, nil +} + +// ConvertCommandUnaryExprToMessageUnaryExpr converts a command.Expr to a message.Expr_Unary. +func ConvertCommandUnaryExprToMessageUnaryExpr(cmd command.UnaryExpr) (*Expr_Unary, error) { + val, err := ConvertCommandExprToMessageExpr(cmd.Value) + if err != nil { + return nil, err + } + return &Expr_Unary{ + &UnaryExpr{ + Operator: cmd.Operator, + Value: val, + }, + }, nil +} + +// ConvertCommandBinaryExprToMessageBinaryExpr converts a command.Expr to a message.Expr_Binary. +func ConvertCommandBinaryExprToMessageBinaryExpr(cmd command.BinaryExpr) (*Expr_Binary, error) { + left, err := ConvertCommandExprToMessageExpr(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandExprToMessageExpr(cmd.Right) + if err != nil { + return nil, err + } + return &Expr_Binary{ + &BinaryExpr{ + Operator: cmd.Operator, + Left: left, + Right: right, + }, + }, nil +} + +// ConvertCommandRepeatedExprToMessageRepeatedExpr converts a []command.Expr to a message.Expr. +func ConvertCommandRepeatedExprToMessageRepeatedExpr(cmd []command.Expr) ([]*Expr, error) { + msgRepeatedExpr := []*Expr{} + for i := range cmd { + expr, err := ConvertCommandExprToMessageExpr(cmd[i]) + if err != nil { + return nil, err + } + msgRepeatedExpr = append(msgRepeatedExpr, expr) + } + return msgRepeatedExpr, nil +} + +// ConvertCommandFunctionalExprToMessageFunctionalExpr converts a command.Expr to a message.Expr_Func. +func ConvertCommandFunctionalExprToMessageFunctionalExpr(cmd command.FunctionExpr) (*Expr_Func, error) { + args, err := ConvertCommandRepeatedExprToMessageRepeatedExpr(cmd.Args) + if err != nil { + return nil, err + } + return &Expr_Func{ + &FunctionExpr{ + Name: cmd.Name, + Distinct: cmd.Distinct, + Args: args, + }, + }, nil +} + +// ConvertCommandEqualityExprToMessageEqualityExpr converts a command.Expr to a message.Expr_Equality. +func ConvertCommandEqualityExprToMessageEqualityExpr(cmd command.EqualityExpr) (*Expr_Equality, error) { + left, err := ConvertCommandExprToMessageExpr(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandExprToMessageExpr(cmd.Right) + if err != nil { + return nil, err + } + return &Expr_Equality{ + &EqualityExpr{ + Left: left, + Right: right, + Invert: cmd.Invert, + }, + }, nil +} + +// ConvertCommandRangeExprToMessageRangeExpr converts a command.Expr to a message.Expr_Range. +func ConvertCommandRangeExprToMessageRangeExpr(cmd command.RangeExpr) (*Expr_Range, error) { + needle, err := ConvertCommandExprToMessageExpr(cmd.Needle) + if err != nil { + return nil, err + } + lo, err := ConvertCommandExprToMessageExpr(cmd.Lo) + if err != nil { + return nil, err + } + hi, err := ConvertCommandExprToMessageExpr(cmd.Hi) + if err != nil { + return nil, err + } + return &Expr_Range{ + &RangeExpr{ + Needle: needle, + Lo: lo, + Hi: hi, + Invert: cmd.Invert, + }, + }, nil +} + +// ConvertCommandExprToMessageExpr converts command.Expr to a message.Expr. +func ConvertCommandExprToMessageExpr(cmd command.Expr) (*Expr, error) { + var err error + msgExpr := &Expr{} + switch c := cmd.(type) { + case command.LiteralExpr: + msgExpr.Expr, err = ConvertCommandLiteralExprToMessageLiteralExpr(c) + if err != nil { + return nil, err + } + case command.ConstantBooleanExpr: + msgExpr.Expr, err = ConvertCommandConstantBooleanExprToMessageConstantBooleanExpr(c) + if err != nil { + return nil, err + } + case command.UnaryExpr: + msgExpr.Expr, err = ConvertCommandUnaryExprToMessageUnaryExpr(c) + if err != nil { + return nil, err + } + case command.BinaryExpr: + msgExpr.Expr, err = ConvertCommandBinaryExprToMessageBinaryExpr(c) + if err != nil { + return nil, err + } + case command.FunctionExpr: + msgExpr.Expr, err = ConvertCommandFunctionalExprToMessageFunctionalExpr(c) + if err != nil { + return nil, err + } + case command.EqualityExpr: + msgExpr.Expr, err = ConvertCommandEqualityExprToMessageEqualityExpr(c) + if err != nil { + return nil, err + } + case command.RangeExpr: + msgExpr.Expr, err = ConvertCommandRangeExprToMessageRangeExpr(c) + if err != nil { + return nil, err + } + default: + return nil, ErrUnknownCommandKind + } + return msgExpr, nil +} + +// ConvertCommandListScanToMessageListScan converts a command.Scan to a message.List_Scan. +func ConvertCommandListScanToMessageListScan(cmd command.Scan) (*List_Scan, error) { + table, err := ConvertCommandTableToMessageTable(cmd.Table) + if err != nil { + return nil, err + } + return &List_Scan{ + &Command_Scan{ + Table: table, + }, + }, nil +} + +// ConvertCommandListSelectToMessageListSelect converts a command.Select to a message.List_Select. +func ConvertCommandListSelectToMessageListSelect(cmd command.Select) (*List_Select, error) { + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &List_Select{ + &Command_Select{ + Filter: filter, + Input: input, + }, + }, nil +} + +// ConvertCommandListProjectToMessageListProject converts a command.Project to a message.List_Project. +func ConvertCommandListProjectToMessageListProject(cmd command.Project) (*List_Project, error) { + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + cols, err := ConvertCommandColSliceToMessageColSlice(cmd.Cols) + if err != nil { + return nil, err + } + return &List_Project{ + &Command_Project{ + Cols: cols, + Input: input, + }, + }, nil +} + +// ConvertCommandListJoinToMessageListJoin converts a command.Join to a message.List_Join. +func ConvertCommandListJoinToMessageListJoin(cmd command.Join) (*List_Join, error) { + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + left, err := ConvertCommandListToMessageList(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandListToMessageList(cmd.Right) + if err != nil { + return nil, err + } + return &List_Join{ + &Command_Join{ + Natural: cmd.Natural, + Type: ConvertCommandJoinTypeToMessageJoinType(cmd.Type), + Filter: filter, + Left: left, + Right: right, + }, + }, nil +} + +// ConvertCommandListLimitToMessageListLimit converts a command.Limit to a message.List_Limit. +func ConvertCommandListLimitToMessageListLimit(cmd command.Limit) (*List_Limit, error) { + limit, err := ConvertCommandExprToMessageExpr(cmd.Limit) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &List_Limit{ + &Command_Limit{ + Limit: limit, + Input: input, + }, + }, nil +} + +// ConvertCommandListOffsetToMessageListOffset converts a command.Offset to a message.List_Offset. +func ConvertCommandListOffsetToMessageListOffset(cmd command.Offset) (*List_Offset, error) { + offset, err := ConvertCommandExprToMessageExpr(cmd.Offset) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &List_Offset{ + &Command_Offset{ + Offset: offset, + Input: input, + }, + }, nil +} + +// ConvertCommandListDistinctToMessageListDistinct converts a command.Distinct to a message.List_Distinct. +func ConvertCommandListDistinctToMessageListDistinct(cmd command.Distinct) (*List_Distinct, error) { + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &List_Distinct{ + &Command_Distinct{ + Input: input, + }, + }, nil +} + +// ConvertCommandRepeatedExprToMessageRepeatedExprSlice converts a [][]command.Expr to a [][]message.Expr. +func ConvertCommandRepeatedExprToMessageRepeatedExprSlice(cmd [][]command.Expr) ([]*RepeatedExpr, error) { + msgRepeatedExprSlice := []*RepeatedExpr{} + for i := range cmd { + msgRepeatedExpr := &RepeatedExpr{} + for j := range cmd[i] { + expr, err := ConvertCommandExprToMessageExpr(cmd[i][j]) + if err != nil { + return nil, err + } + msgRepeatedExpr.Expr = append(msgRepeatedExpr.Expr, expr) + } + msgRepeatedExprSlice = append(msgRepeatedExprSlice, msgRepeatedExpr) + } + return msgRepeatedExprSlice, nil +} + +// ConvertCommandListValuesToMessageListValues converts a command.Values to a message.List_Values. +func ConvertCommandListValuesToMessageListValues(cmd command.Values) (*List_Values, error) { + exprSlice, err := ConvertCommandRepeatedExprToMessageRepeatedExprSlice(cmd.Values) + if err != nil { + return nil, err + } + return &List_Values{ + &Command_Values{ + Expr: exprSlice, + }, + }, nil +} + +// ConvertCommandListToMessageList converts a command.List to a message.List. +func ConvertCommandListToMessageList(cmd command.List) (*List, error) { + var err error + msgList := &List{} + switch c := cmd.(type) { + case command.Scan: + msgList.List, err = ConvertCommandListScanToMessageListScan(c) + if err != nil { + return nil, err + } + case command.Select: + msgList.List, err = ConvertCommandListSelectToMessageListSelect(c) + if err != nil { + return nil, err + } + case command.Project: + msgList.List, err = ConvertCommandListProjectToMessageListProject(c) + if err != nil { + return nil, err + } + case command.Join: + msgList.List, err = ConvertCommandListJoinToMessageListJoin(c) + if err != nil { + return nil, err + } + case command.Limit: + msgList.List, err = ConvertCommandListLimitToMessageListLimit(c) + if err != nil { + return nil, err + } + case command.Offset: + msgList.List, err = ConvertCommandListOffsetToMessageListOffset(c) + if err != nil { + return nil, err + } + case command.Distinct: + msgList.List, err = ConvertCommandListDistinctToMessageListDistinct(c) + if err != nil { + return nil, err + } + case command.Values: + msgList.List, err = ConvertCommandListValuesToMessageListValues(c) + if err != nil { + return nil, err + } + default: + return nil, ErrUnknownCommandKind + } + return msgList, nil +} + +// ConvertCommandSelectToMessageSelect converts a Command type to a Command_Select type. +func ConvertCommandSelectToMessageSelect(cmd command.Select) (*Command_Select, error) { + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &Command_Select{ + Filter: filter, + Input: input, + }, nil +} + +// ConvertCommandColToMessageCol converts command.Column to a message.Column. +func ConvertCommandColToMessageCol(cmd command.Column) (*Column, error) { + column, err := ConvertCommandExprToMessageExpr(cmd.Column) + if err != nil { + return nil, err + } + return &Column{ + Table: cmd.Table, + Column: column, + Alias: cmd.Alias, + }, nil +} + +// ConvertCommandColSliceToMessageColSlice converts []command.Column to a []message.Column. +func ConvertCommandColSliceToMessageColSlice(cmd []command.Column) ([]*Column, error) { + msgCols := []*Column{} + for i := range cmd { + col, err := ConvertCommandColToMessageCol(cmd[i]) + if err != nil { + return nil, err + } + msgCols = append(msgCols, col) + } + return msgCols, nil +} + +// ConvertCommandProjectToMessageProject converts a Command type to a Command_Project type. +func ConvertCommandProjectToMessageProject(cmd command.Project) (*Command_Project, error) { + cols, err := ConvertCommandColSliceToMessageColSlice(cmd.Cols) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &Command_Project{ + Cols: cols, + Input: input, + }, nil +} + +// ConvertCommandDeleteToMessageDelete converts a Command type to a Command_Delete type. +func ConvertCommandDeleteToMessageDelete(cmd command.Delete) (*Command_Delete, error) { + table, err := ConvertCommandTableToMessageTable(cmd.Table) + if err != nil { + return nil, err + } + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + return &Command_Delete{ + Table: table, + Filter: filter, + }, nil +} + +// ConvertCommandDropToMessageDrop converts a Command type to a CommandDrop type. +func ConvertCommandDropToMessageDrop(cmd command.Command) (*CommandDrop, error) { + if cmd == nil { + return nil, ErrNilCommand + } + msgCmdDrop := &CommandDrop{} + switch c := cmd.(type) { + case *command.DropTable: + msgCmdDrop.Target = DropTarget_Table + msgCmdDrop.IfExists = c.IfExists + msgCmdDrop.Schema = c.Schema + msgCmdDrop.Name = c.Name + case *command.DropView: + msgCmdDrop.Target = DropTarget_View + msgCmdDrop.IfExists = c.IfExists + msgCmdDrop.Schema = c.Schema + msgCmdDrop.Name = c.Name + case *command.DropIndex: + msgCmdDrop.Target = DropTarget_Index + msgCmdDrop.IfExists = c.IfExists + msgCmdDrop.Schema = c.Schema + msgCmdDrop.Name = c.Name + case *command.DropTrigger: + msgCmdDrop.Target = DropTarget_Trigger + msgCmdDrop.IfExists = c.IfExists + msgCmdDrop.Schema = c.Schema + msgCmdDrop.Name = c.Name + } + return msgCmdDrop, nil +} + +// ConvertCommandUpdateOrToMessageUpdateOr converts a command.Update or to a message.UpdateOr. +// Returns -1 if the UpdateOr type doesn't match. +func ConvertCommandUpdateOrToMessageUpdateOr(cmd command.UpdateOr) (UpdateOr, error) { + switch cmd { + case command.UpdateOrUnknown: + return UpdateOr_UpdateOrUnknown, nil + case command.UpdateOrRollback: + return UpdateOr_UpdateOrRollback, nil + case command.UpdateOrAbort: + return UpdateOr_UpdateOrAbort, nil + case command.UpdateOrReplace: + return UpdateOr_UpdateOrReplace, nil + case command.UpdateOrFail: + return UpdateOr_UpdateOrFail, nil + case command.UpdateOrIgnore: + return UpdateOr_UpdateOrIgnore, nil + } + return -1, ErrUnknownCommandKind +} + +// ConvertCommandUpdateSetterLiteralToMessageUpdateSetterLiteral converts +// a command.Literal to a message.UpdateSetter_Literal. +func ConvertCommandUpdateSetterLiteralToMessageUpdateSetterLiteral( + cmd command.LiteralExpr, +) (*UpdateSetter_Literal, error) { + return &UpdateSetter_Literal{ + &LiteralExpr{ + Value: cmd.Value, + }, + }, nil +} + +// ConvertCommandUpdateSetterConstantToMessageUpdateSetterConstant converts +// a command.Constant to a message.UpdateSetter_Constant. +func ConvertCommandUpdateSetterConstantToMessageUpdateSetterConstant( + cmd command.ConstantBooleanExpr, +) (*UpdateSetter_Constant, error) { + + return &UpdateSetter_Constant{ + &ConstantBooleanExpr{ + Value: cmd.Value, + }, + }, nil +} + +// ConvertCommandUpdateSetterUnaryToMessageUpdateSetterUnary converts +// a command.Unary to a message.UpdateSetter_Unary. +func ConvertCommandUpdateSetterUnaryToMessageUpdateSetterUnary( + cmd command.UnaryExpr, +) (*UpdateSetter_Unary, error) { + val, err := ConvertCommandExprToMessageExpr(cmd.Value) + if err != nil { + return nil, err + } + return &UpdateSetter_Unary{ + &UnaryExpr{ + Operator: cmd.Operator, + Value: val, + }, + }, nil +} + +// ConvertCommandUpdateSetterBinaryToMessageUpdateSetterBinary converts +// a command.Binary to a message.UpdateSetter_Binary. +func ConvertCommandUpdateSetterBinaryToMessageUpdateSetterBinary( + cmd command.BinaryExpr, +) (*UpdateSetter_Binary, error) { + left, err := ConvertCommandExprToMessageExpr(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandExprToMessageExpr(cmd.Right) + if err != nil { + return nil, err + } + return &UpdateSetter_Binary{ + &BinaryExpr{ + Operator: cmd.Operator, + Left: left, + Right: right, + }, + }, nil +} + +// ConvertCommandUpdateSetterFuncToMessageUpdateSetterFunc converts +// a command.Func to a message.UpdateSetter_Func. +func ConvertCommandUpdateSetterFuncToMessageUpdateSetterFunc( + cmd command.FunctionExpr, +) (*UpdateSetter_Func, error) { + repExpr, err := ConvertCommandRepeatedExprToMessageRepeatedExpr(cmd.Args) + if err != nil { + return nil, err + } + return &UpdateSetter_Func{ + &FunctionExpr{ + Name: cmd.Name, + Distinct: cmd.Distinct, + Args: repExpr, + }, + }, nil +} + +// ConvertCommandUpdateSetterEqualityToMessageUpdateSetterEquality converts +// a command.Equality to a message.UpdateSetter_Equality. +func ConvertCommandUpdateSetterEqualityToMessageUpdateSetterEquality( + cmd command.EqualityExpr, +) (*UpdateSetter_Equality, error) { + left, err := ConvertCommandExprToMessageExpr(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandExprToMessageExpr(cmd.Right) + if err != nil { + return nil, err + } + return &UpdateSetter_Equality{ + &EqualityExpr{ + Left: left, + Right: right, + Invert: cmd.Invert, + }, + }, nil +} + +// ConvertCommandUpdateSetterRangeToMessageUpdateSetterRange converts +// a command.Range to a message.UpdateSetter_Range. +func ConvertCommandUpdateSetterRangeToMessageUpdateSetterRange( + cmd command.RangeExpr, +) (*UpdateSetter_Range, error) { + needle, err := ConvertCommandExprToMessageExpr(cmd.Needle) + if err != nil { + return nil, err + } + lo, err := ConvertCommandExprToMessageExpr(cmd.Lo) + if err != nil { + return nil, err + } + hi, err := ConvertCommandExprToMessageExpr(cmd.Hi) + if err != nil { + return nil, err + } + return &UpdateSetter_Range{ + &RangeExpr{ + Needle: needle, + Lo: lo, + Hi: hi, + Invert: cmd.Invert, + }, + }, nil +} + +// ConvertCommandUpdateSetterToMessageUpdateSetter converts +// a command.UpdateSetter to a message.UpdateSetter. +func ConvertCommandUpdateSetterToMessageUpdateSetter( + cmd command.UpdateSetter, +) (*UpdateSetter, error) { + var err error + msgUpdateSetter := &UpdateSetter{} + msgUpdateSetter.Cols = cmd.Cols + switch val := cmd.Value.(type) { + case command.LiteralExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterLiteralToMessageUpdateSetterLiteral(val) + if err != nil { + return nil, err + } + case command.ConstantBooleanExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterConstantToMessageUpdateSetterConstant(val) + if err != nil { + return nil, err + } + case command.UnaryExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterUnaryToMessageUpdateSetterUnary(val) + if err != nil { + return nil, err + } + case command.BinaryExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterBinaryToMessageUpdateSetterBinary(val) + if err != nil { + return nil, err + } + case command.FunctionExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterFuncToMessageUpdateSetterFunc(val) + if err != nil { + return nil, err + } + case command.EqualityExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterEqualityToMessageUpdateSetterEquality(val) + if err != nil { + return nil, err + } + case command.RangeExpr: + msgUpdateSetter.Value, err = ConvertCommandUpdateSetterRangeToMessageUpdateSetterRange(val) + if err != nil { + return nil, err + } + } + return msgUpdateSetter, nil +} + +// ConvertCommandUpdateSetterSliceToMessageUpdateSetterSlice converts +// a []command.UpdateSetter to a []message.UpdateSetter. +func ConvertCommandUpdateSetterSliceToMessageUpdateSetterSlice( + cmd []command.UpdateSetter, +) ([]*UpdateSetter, error) { + msgUpdateSetterSlice := []*UpdateSetter{} + for i := range cmd { + updateSetter, err := ConvertCommandUpdateSetterToMessageUpdateSetter(cmd[i]) + if err != nil { + return nil, err + } + msgUpdateSetterSlice = append(msgUpdateSetterSlice, updateSetter) + } + return msgUpdateSetterSlice, nil +} + +// ConvertCommandUpdateToMessageUpdate converts a Command type to a Command_Update type. +func ConvertCommandUpdateToMessageUpdate(cmd command.Update) (*Command_Update, error) { + updateOr, err := ConvertCommandUpdateOrToMessageUpdateOr(cmd.UpdateOr) + if err != nil { + return nil, err + } + table, err := ConvertCommandTableToMessageTable(cmd.Table) + if err != nil { + return nil, err + } + updates, err := ConvertCommandUpdateSetterSliceToMessageUpdateSetterSlice(cmd.Updates) + if err != nil { + return nil, err + } + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + return &Command_Update{ + UpdateOr: updateOr, + Table: table, + Updates: updates, + Filter: filter, + }, nil +} + +// ConvertCommandJoinTypeToMessageJoinType converts command.JoinType to message.JoinType. +// It returns -1 on not finding a valid JoinType. +func ConvertCommandJoinTypeToMessageJoinType(cmd command.JoinType) JoinType { + switch cmd { + case command.JoinUnknown: + return JoinType_JoinUnknown + case command.JoinLeft: + return JoinType_JoinLeft + case command.JoinLeftOuter: + return JoinType_JoinLeftOuter + case command.JoinInner: + return JoinType_JoinInner + case command.JoinCross: + return JoinType_JoinCross + } + return -1 +} + +// ConvertCommandJoinToMessageJoin converts a Command type to a Command_Join type. +func ConvertCommandJoinToMessageJoin(cmd command.Join) (*Command_Join, error) { + filter, err := ConvertCommandExprToMessageExpr(cmd.Filter) + if err != nil { + return nil, err + } + left, err := ConvertCommandListToMessageList(cmd.Left) + if err != nil { + return nil, err + } + right, err := ConvertCommandListToMessageList(cmd.Right) + if err != nil { + return nil, err + } + + return &Command_Join{ + Natural: cmd.Natural, + Type: ConvertCommandJoinTypeToMessageJoinType(cmd.Type), + Filter: filter, + Left: left, + Right: right, + }, nil +} + +// ConvertCommandLimitToMessageLimit converts a Command type to a Command_Limit type. +func ConvertCommandLimitToMessageLimit(cmd command.Limit) (*Command_Limit, error) { + limit, err := ConvertCommandExprToMessageExpr(cmd.Limit) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &Command_Limit{ + Limit: limit, + Input: input, + }, nil +} + +// ConvertCommandInsertOrToMessageInsertOr converts command.InsertOr to a message.InsertOr. +// It returns -1 on not finding the right InsertOr type. +func ConvertCommandInsertOrToMessageInsertOr(cmd command.InsertOr) InsertOr { + switch cmd { + case command.InsertOrUnknown: + return InsertOr_InsertOrUnknown + case command.InsertOrReplace: + return InsertOr_InsertOrReplace + case command.InsertOrRollback: + return InsertOr_InsertOrRollback + case command.InsertOrAbort: + return InsertOr_InsertOrAbort + case command.InsertOrFail: + return InsertOr_InsertOrFail + case command.InsertOrIgnore: + return InsertOr_InsertOrIgnore + } + return -1 +} + +// ConvertCommandInsertToMessageInsert converts a Command type to a Command_Insert type. +func ConvertCommandInsertToMessageInsert(cmd command.Insert) (*Command_Insert, error) { + table, err := ConvertCommandTableToMessageTable(cmd.Table) + if err != nil { + return nil, err + } + colSlice, err := ConvertCommandColSliceToMessageColSlice(cmd.Cols) + if err != nil { + return nil, err + } + input, err := ConvertCommandListToMessageList(cmd.Input) + if err != nil { + return nil, err + } + return &Command_Insert{ + InsertOr: ConvertCommandInsertOrToMessageInsertOr(cmd.InsertOr), + Table: table, + Cols: colSlice, + DefaultValues: cmd.DefaultValues, + Input: input, + }, nil +} + +// ConvertMessageToCommand converts a message.Command to a command.Command. +func ConvertMessageToCommand(msg Message) command.Command { + switch m := msg.(type) { + case *Command_Scan: + return ConvertMessageScanToCommandScan(m) + case *Command_Select: + return ConvertMessageSelectToCommandSelect(m) + case *Command_Project: + return ConvertMessageProjectToCommandProject(m) + case *Command_Delete: + return ConvertMessageDeleteToCommandDelete(m) + case *CommandDrop: + switch m.Target { + case 0: + return ConvertMessageDropToCommandDropTable(m) + case 1: + return ConvertMessageDropToCommandDropView(m) + case 2: + return ConvertMessageDropToCommandDropIndex(m) + case 3: + return ConvertMessageDropToCommandDropTrigger(m) + } + case *Command_Update: + return ConvertMessageUpdateToCommandUpdate(m) + case *Command_Join: + return ConvertMessageJoinToCommandJoin(m) + case *Command_Limit: + return ConvertMessageLimitToCommandLimit(m) + case *Command_Insert: + return ConvertMessageInsertToCommandInsert(m) + } + return nil +} + +// ConvertMessageTableToCommandTable converts a message.SimpleTable to a command.Table. +func ConvertMessageTableToCommandTable(msg *SimpleTable) command.Table { + return &command.SimpleTable{ + Schema: msg.Schema, + Table: msg.Table, + Alias: msg.Alias, + Indexed: msg.Indexed, + Index: msg.Index, + } +} + +// ConvertMessageScanToCommandScan converts a message.Command_Scan to a command.Scan. +func ConvertMessageScanToCommandScan(msg *Command_Scan) command.Scan { + return command.Scan{ + Table: ConvertMessageTableToCommandTable(msg.Table), + } +} + +// ConvertMessageLiteralExprToCommandLiteralExpr converts a message.Expr to a command.LiteralExpr. +func ConvertMessageLiteralExprToCommandLiteralExpr(msg *Expr) command.LiteralExpr { + return command.LiteralExpr{ + Value: msg.GetLiteral().GetValue(), + } +} + +// ConvertMessageBooleanExprToCommandConstantBooleanExpr converts a message.Expr to a command.ConstantBooleanExpr. +func ConvertMessageBooleanExprToCommandConstantBooleanExpr(msg *Expr) command.ConstantBooleanExpr { + return command.ConstantBooleanExpr{ + Value: msg.GetConstant().GetValue(), + } +} + +// ConvertMessageUnaryExprToCommandUnaryExpr converts a message.Expr to a command.UnaryExpr. +func ConvertMessageUnaryExprToCommandUnaryExpr(msg *Expr) command.UnaryExpr { + return command.UnaryExpr{ + Operator: msg.GetUnary().GetOperator(), + Value: ConvertMessageExprToCommandExpr(msg.GetUnary().GetValue()), + } +} + +// ConvertMessageBinaryExprToCommandBinaryExpr converts a message.Expr to a command.BinaryExpr. +func ConvertMessageBinaryExprToCommandBinaryExpr(msg *Expr) command.BinaryExpr { + return command.BinaryExpr{ + Operator: msg.GetBinary().GetOperator(), + Left: ConvertMessageExprToCommandExpr(msg.GetBinary().GetLeft()), + Right: ConvertMessageExprToCommandExpr(msg.GetBinary().GetRight()), + } +} + +// ConvertMessageExprSliceToCommandExprSlice converts a []*message.Expr to []command.Expr. +func ConvertMessageExprSliceToCommandExprSlice(msg []*Expr) []command.Expr { + msgExprSlice := []command.Expr{} + for i := range msg { + msgExprSlice = append(msgExprSlice, ConvertMessageExprToCommandExpr(msg[i])) + } + return msgExprSlice +} + +// ConvertMessageFunctionalExprToCommandFunctionExpr converts a message.Expr to a command.FunctionExpr. +func ConvertMessageFunctionalExprToCommandFunctionExpr(msg *Expr) command.FunctionExpr { + return command.FunctionExpr{ + Name: msg.GetFunc().GetName(), + Distinct: msg.GetFunc().GetDistinct(), + Args: ConvertMessageExprSliceToCommandExprSlice(msg.GetFunc().GetArgs()), + } +} + +// ConvertMessageEqualityExprToCommandEqualityExpr converts a message.Expr to a command.EqualityExpr. +func ConvertMessageEqualityExprToCommandEqualityExpr(msg *Expr) command.EqualityExpr { + return command.EqualityExpr{ + Left: ConvertMessageExprToCommandExpr(msg.GetEquality().GetLeft()), + Right: ConvertMessageExprToCommandExpr(msg.GetEquality().GetRight()), + Invert: msg.GetEquality().Invert, + } +} + +// ConvertMessageRangeExprToCommandRangeExpr converts a message.Expr to a command.RangeExpr. +func ConvertMessageRangeExprToCommandRangeExpr(msg *Expr) command.RangeExpr { + return command.RangeExpr{ + Needle: ConvertMessageExprToCommandExpr(msg.GetRange().GetNeedle()), + Lo: ConvertMessageExprToCommandExpr(msg.GetRange().GetLo()), + Hi: ConvertMessageExprToCommandExpr(msg.GetRange().GetHi()), + } +} + +// ConvertMessageExprToCommandExpr converts a message.Expr to a command.Expr. +func ConvertMessageExprToCommandExpr(msg *Expr) command.Expr { + if msg == nil { + return nil + } + switch msg.Expr.(type) { + case *Expr_Literal: + return ConvertMessageLiteralExprToCommandLiteralExpr(msg) + case *Expr_Constant: + return ConvertMessageBooleanExprToCommandConstantBooleanExpr(msg) + case *Expr_Unary: + return ConvertMessageUnaryExprToCommandUnaryExpr(msg) + case *Expr_Binary: + return ConvertMessageBinaryExprToCommandBinaryExpr(msg) + case *Expr_Func: + return ConvertMessageFunctionalExprToCommandFunctionExpr(msg) + case *Expr_Equality: + return ConvertMessageEqualityExprToCommandEqualityExpr(msg) + case *Expr_Range: + return ConvertMessageRangeExprToCommandRangeExpr(msg) + } + return nil +} + +// ConvertMessageListScanToCommandListScan converts a message.List to a command.Scan. +func ConvertMessageListScanToCommandListScan(msg *List) command.Scan { + return command.Scan{ + Table: ConvertMessageTableToCommandTable(msg.GetScan().GetTable()), + } +} + +// ConvertMessageListSelectToCommandListSelect converts a message.List to a command.Select. +func ConvertMessageListSelectToCommandListSelect(msg *List) command.Select { + return command.Select{ + Filter: ConvertMessageExprToCommandExpr(msg.GetSelect().GetFilter()), + Input: ConvertMessageListToCommandList(msg.GetSelect().GetInput()), + } +} + +// ConvertMessageListProjectToCommandListProject converts a message.List to a command.Project. +func ConvertMessageListProjectToCommandListProject(msg *List) command.Project { + return command.Project{ + Cols: ConvertMessageColsToCommandCols(msg.GetProject().GetCols()), + Input: ConvertMessageListToCommandList(msg.GetProject().GetInput()), + } +} + +// ConvertMessageListJoinToCommandListJoin converts a message.List to a command.Join. +func ConvertMessageListJoinToCommandListJoin(msg *List) command.Join { + return command.Join{ + Natural: msg.GetJoin().GetNatural(), + Type: ConvertMessageJoinTypeToCommandJoinType(msg.GetJoin().GetType()), + Filter: ConvertMessageExprToCommandExpr(msg.GetJoin().GetFilter()), + Left: ConvertMessageListToCommandList(msg.GetJoin().GetLeft()), + Right: ConvertMessageListToCommandList(msg.GetJoin().GetRight()), + } +} + +// ConvertMessageListLimitToCommandListLimit converts a message.List to a command.Limit. +func ConvertMessageListLimitToCommandListLimit(msg *List) command.Limit { + return command.Limit{ + Limit: ConvertMessageExprToCommandExpr(msg.GetLimit().GetLimit()), + Input: ConvertMessageListToCommandList(msg.GetLimit().GetInput()), + } +} + +// ConvertMessageListOffsetToCommandListOffset converts a message.List to a command.Offset. +func ConvertMessageListOffsetToCommandListOffset(msg *List) command.Offset { + return command.Offset{ + Offset: ConvertMessageExprToCommandExpr(msg.GetOffset().GetOffset()), + Input: ConvertMessageListToCommandList(msg.GetDistinct().GetInput()), + } +} + +// ConvertMessageListDistinctToCommandListDistinct converts a message.List to a command.Distinct. +func ConvertMessageListDistinctToCommandListDistinct(msg *List) command.Distinct { + return command.Distinct{ + Input: ConvertMessageListToCommandList(msg.GetDistinct().GetInput()), + } +} + +// ConvertMessageExprToCommandExprRepeatedSlice converts a message.RepeatedExpr to a [][]command.Expr. +func ConvertMessageExprToCommandExprRepeatedSlice(msg []*RepeatedExpr) [][]command.Expr { + cmdRepeatedExprSlice := [][]command.Expr{} + for i := range msg { + cmdRepeatedExpr := []command.Expr{} + for j := range msg[i].Expr { + cmdRepeatedExpr = append(cmdRepeatedExpr, ConvertMessageExprToCommandExpr(msg[i].Expr[j])) + } + cmdRepeatedExprSlice = append(cmdRepeatedExprSlice, cmdRepeatedExpr) + } + return cmdRepeatedExprSlice +} + +// ConvertMessageListValuesToCommandListValues converts a message.List to a command.Values. +func ConvertMessageListValuesToCommandListValues(msg *List) command.Values { + return command.Values{ + Values: ConvertMessageExprToCommandExprRepeatedSlice(msg.GetValues().GetExpr()), + } +} + +// ConvertMessageListToCommandList converts a message.List to a command.List. +func ConvertMessageListToCommandList(msg *List) command.List { + if msg == nil { + return nil + } + switch msg.List.(type) { + case *List_Scan: + return ConvertMessageListScanToCommandListScan(msg) + case *List_Select: + return ConvertMessageListSelectToCommandListSelect(msg) + case *List_Project: + return ConvertMessageListProjectToCommandListProject(msg) + case *List_Join: + return ConvertMessageListJoinToCommandListJoin(msg) + case *List_Limit: + return ConvertMessageListLimitToCommandListLimit(msg) + case *List_Offset: + return ConvertMessageListOffsetToCommandListOffset(msg) + case *List_Distinct: + return ConvertMessageListDistinctToCommandListDistinct(msg) + case *List_Values: + return ConvertMessageListValuesToCommandListValues(msg) + } + return nil +} + +// ConvertMessageSelectToCommandSelect converts a message.Command_Select to a command.Select. +func ConvertMessageSelectToCommandSelect(msg *Command_Select) command.Select { + return command.Select{ + Filter: ConvertMessageExprToCommandExpr(msg.GetFilter()), + Input: ConvertMessageListToCommandList(msg.GetInput()), + } +} + +// ConvertMessageColToCommandCol converts a message.Column to a command.Column. +func ConvertMessageColToCommandCol(msg *Column) command.Column { + return command.Column{ + Table: msg.GetTable(), + Column: ConvertMessageExprToCommandExpr(msg.GetColumn()), + Alias: msg.GetAlias(), + } +} + +// ConvertMessageColsToCommandCols converts a []message.Column to a []command.Column. +func ConvertMessageColsToCommandCols(msg []*Column) []command.Column { + cmdCols := []command.Column{} + for i := range msg { + cmdCols = append(cmdCols, ConvertMessageColToCommandCol(msg[i])) + } + return cmdCols +} + +// ConvertMessageProjectToCommandProject converts a message.Command_Project to a command.Project. +func ConvertMessageProjectToCommandProject(msg *Command_Project) command.Project { + return command.Project{ + Cols: ConvertMessageColsToCommandCols(msg.GetCols()), + Input: ConvertMessageListToCommandList(msg.GetInput()), + } +} + +// ConvertMessageDeleteToCommandDelete converts a message.Command_Delete to a command.Delete. +func ConvertMessageDeleteToCommandDelete(msg *Command_Delete) command.Delete { + return command.Delete{ + Filter: ConvertMessageExprToCommandExpr(msg.GetFilter()), + Table: ConvertMessageTableToCommandTable(msg.GetTable()), + } +} + +// ConvertMessageDropToCommandDropTable converts a message.CommandDrop to a command.Drop. +func ConvertMessageDropToCommandDropTable(msg *CommandDrop) command.DropTable { + return command.DropTable{ + IfExists: msg.GetIfExists(), + Schema: msg.GetSchema(), + Name: msg.GetName(), + } +} + +// ConvertMessageDropToCommandDropView converts a message.CommandDrop to a command.Drop. +func ConvertMessageDropToCommandDropView(msg *CommandDrop) command.DropView { + return command.DropView{ + IfExists: msg.GetIfExists(), + Schema: msg.GetSchema(), + Name: msg.GetName(), + } +} + +// ConvertMessageDropToCommandDropIndex converts a message.CommandDrop to a command.Drop. +func ConvertMessageDropToCommandDropIndex(msg *CommandDrop) command.DropIndex { + return command.DropIndex{ + IfExists: msg.GetIfExists(), + Schema: msg.GetSchema(), + Name: msg.GetName(), + } +} + +// ConvertMessageDropToCommandDropTrigger converts a message.CommandDrop to a command.Drop. +func ConvertMessageDropToCommandDropTrigger(msg *CommandDrop) command.DropTrigger { + return command.DropTrigger{ + IfExists: msg.GetIfExists(), + Schema: msg.GetSchema(), + Name: msg.GetName(), + } +} + +// ConvertMessageUpdateOrToCommandUpdateOr converts a message.UpdateOr to command.UpdateOr. +func ConvertMessageUpdateOrToCommandUpdateOr(msg UpdateOr) command.UpdateOr { + return command.UpdateOr(msg.Number()) +} + +// ConvertMessageUpdateSetterLiteralExprToCommandUpdateSetterLiteralExpr converts +// a message.LiteralExpr to command.Expr. +func ConvertMessageUpdateSetterLiteralExprToCommandUpdateSetterLiteralExpr( + msg *LiteralExpr, +) command.Expr { + return command.LiteralExpr{ + Value: msg.Value, + } +} + +// ConvertMessageUpdateSetterConstantExprToCommandUpdateSetterConstantExpr converts +// a message.ConstantBooleanExpr to a command.Expr. +func ConvertMessageUpdateSetterConstantExprToCommandUpdateSetterConstantExpr( + msg *ConstantBooleanExpr, +) command.Expr { + return command.ConstantBooleanExpr{ + Value: msg.Value, + } +} + +// ConvertMessageUpdateSetterUnaryExprToCommandUpdateSetterUnaryExpr converts +// a message.UnaryExpr to command.Expr. +func ConvertMessageUpdateSetterUnaryExprToCommandUpdateSetterUnaryExpr( + msg *UnaryExpr, +) command.Expr { + return command.UnaryExpr{ + Operator: msg.Operator, + Value: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Value), + } +} + +// ConvertMessageUpdateSetterBinaryExprToCommandUpdateSetterBinaryExpr converts +// a message.BinaryExpr to command.Expr. +func ConvertMessageUpdateSetterBinaryExprToCommandUpdateSetterBinaryExpr( + msg *BinaryExpr, +) command.Expr { + return command.BinaryExpr{ + Operator: msg.Operator, + Left: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Left), + Right: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Right), + } +} + +// ConvertMessageUpdateSetterFuncExprToCommandUpdateSetterFuncExpr converts +// a message.FunctionExpr tp command.Expr. +func ConvertMessageUpdateSetterFuncExprToCommandUpdateSetterFuncExpr( + msg *FunctionExpr, +) command.Expr { + return command.FunctionExpr{ + Name: msg.Name, + Distinct: msg.Distinct, + Args: ConvertMessageExprSliceToCommandExprSlice(msg.Args), + } +} + +// ConvertMessageUpdateEqualityExprToCommandUpdateSetterEqualityExpr converts +// a message.EqualityExpr to a command.Expr. +func ConvertMessageUpdateEqualityExprToCommandUpdateSetterEqualityExpr( + msg *EqualityExpr, +) command.Expr { + return command.EqualityExpr{ + Left: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Left), + Right: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Right), + Invert: msg.Invert, + } +} + +// ConvertMessageUpdateSetterRangeExprToCommandUpdateSetterRangeExpr converts +// a message.RangeExpr to a command.Expr. +func ConvertMessageUpdateSetterRangeExprToCommandUpdateSetterRangeExpr( + msg *RangeExpr, +) command.Expr { + return command.RangeExpr{ + Needle: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Needle), + Lo: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Lo), + Hi: ConvertMessageBinaryExprToCommandBinaryExpr(msg.Hi), + Invert: msg.Invert, + } +} + +// ConvertMessageUpdateSetterToCommandUpdateSetter converts +// a message.UpdateSetter to a command.UpdateSetter. +func ConvertMessageUpdateSetterToCommandUpdateSetter(msg *UpdateSetter) command.UpdateSetter { + cmdUpdateSetter := command.UpdateSetter{} + cmdUpdateSetter.Cols = msg.Cols + switch msg.Value.(type) { + case *UpdateSetter_Literal: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterLiteralExprToCommandUpdateSetterLiteralExpr(msg.GetLiteral()) + case *UpdateSetter_Constant: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterConstantExprToCommandUpdateSetterConstantExpr(msg.GetConstant()) + case *UpdateSetter_Unary: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterUnaryExprToCommandUpdateSetterUnaryExpr(msg.GetUnary()) + case *UpdateSetter_Binary: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterBinaryExprToCommandUpdateSetterBinaryExpr(msg.GetBinary()) + case *UpdateSetter_Func: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterFuncExprToCommandUpdateSetterFuncExpr(msg.GetFunc()) + case *UpdateSetter_Equality: + cmdUpdateSetter.Value = ConvertMessageUpdateEqualityExprToCommandUpdateSetterEqualityExpr(msg.GetEquality()) + case *UpdateSetter_Range: + cmdUpdateSetter.Value = ConvertMessageUpdateSetterRangeExprToCommandUpdateSetterRangeExpr(msg.GetRange()) + } + return cmdUpdateSetter +} + +// ConvertMessageUpdateSetterSliceToCommandUpdateSetterSlice converts +// a []message.UpdateSetter to a []command.UpdateSetter. +func ConvertMessageUpdateSetterSliceToCommandUpdateSetterSlice( + msg []*UpdateSetter, +) []command.UpdateSetter { + cmdUpdateSetterSlice := []command.UpdateSetter{} + for i := range msg { + cmdUpdateSetterSlice = append(cmdUpdateSetterSlice, ConvertMessageUpdateSetterToCommandUpdateSetter(msg[i])) + } + return cmdUpdateSetterSlice +} + +// ConvertMessageUpdateToCommandUpdate converts a message.Command_Update to a command.Update. +func ConvertMessageUpdateToCommandUpdate(msg *Command_Update) command.Update { + return command.Update{ + UpdateOr: ConvertMessageUpdateOrToCommandUpdateOr(msg.GetUpdateOr()), + Updates: ConvertMessageUpdateSetterSliceToCommandUpdateSetterSlice(msg.GetUpdates()), + Table: ConvertMessageTableToCommandTable(msg.GetTable()), + Filter: ConvertMessageExprToCommandExpr(msg.GetFilter()), + } +} + +// ConvertMessageJoinTypeToCommandJoinType converts a message.JoinType to a command.JoinType. +func ConvertMessageJoinTypeToCommandJoinType(msg JoinType) command.JoinType { + return command.JoinType(msg.Number()) +} + +// ConvertMessageJoinToCommandJoin converts a message.Command_Join to a command.Join. +func ConvertMessageJoinToCommandJoin(msg *Command_Join) command.Join { + return command.Join{ + Natural: msg.Natural, + Type: ConvertMessageJoinTypeToCommandJoinType(msg.GetType()), + Filter: ConvertMessageExprToCommandExpr(msg.GetFilter()), + Left: ConvertMessageListToCommandList(msg.GetLeft()), + Right: ConvertMessageListToCommandList(msg.GetRight()), + } +} + +// ConvertMessageLimitToCommandLimit converts a message.Command_Limit to a command.Limit. +func ConvertMessageLimitToCommandLimit(msg *Command_Limit) command.Limit { + return command.Limit{ + Limit: ConvertMessageExprToCommandExpr(msg.GetLimit()), + Input: ConvertMessageListToCommandList(msg.GetInput()), + } +} + +// ConvertMessageInsertOrToCommandInsertOr converts a message.InsertOr to command.InsertOr. +func ConvertMessageInsertOrToCommandInsertOr(msg InsertOr) command.InsertOr { + return command.InsertOr(msg.Number()) +} + +// ConvertMessageInsertToCommandInsert converts a message.Command_Insert to a command.Insert +func ConvertMessageInsertToCommandInsert(msg *Command_Insert) command.Insert { + return command.Insert{ + InsertOr: ConvertMessageInsertOrToCommandInsertOr(msg.GetInsertOr()), + Table: ConvertMessageTableToCommandTable(msg.GetTable()), + Cols: ConvertMessageColsToCommandCols(msg.GetCols()), + DefaultValues: msg.GetDefaultValues(), + Input: ConvertMessageListToCommandList(msg.GetInput()), + } +} diff --git a/internal/raft/message/convert_test.go b/internal/raft/message/convert_test.go new file mode 100644 index 00000000..57a66245 --- /dev/null +++ b/internal/raft/message/convert_test.go @@ -0,0 +1,1178 @@ +package message + +import ( + "reflect" + "testing" + + "github.com/tomarrell/lbadd/internal/compiler/command" +) + +var commandToMessageTests = []struct { + in command.Command + out Message +}{ + { + // SCAN + command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + { + // SELECT + command.Select{ + Filter: command.LiteralExpr{ + Value: "literal", + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + &Command_Select{ + Filter: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + }, + { + // PROJECT + command.Project{ + Cols: []command.Column{ + { + Table: "myTable1", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias2", + }, + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + &Command_Project{ + Cols: []*Column{ + { + Table: "myTable1", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias2", + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + }, + { + // DELETE + command.Delete{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Filter: command.BinaryExpr{ + Operator: "operator", + Left: command.LiteralExpr{ + Value: "leftLiteral", + }, + Right: command.LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + &Command_Delete{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Filter: &Expr{ + Expr: &Expr_Binary{ + Binary: &BinaryExpr{ + Operator: "operator", + Left: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "leftLiteral", + }, + }, + }, + Right: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + }, + }, + }, + }, + { + // DROP TABLE + &command.DropTable{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + &CommandDrop{ + Target: 0, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP VIEW + &command.DropView{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + &CommandDrop{ + Target: 1, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP INDEX + &command.DropIndex{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + &CommandDrop{ + Target: 2, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP TRIGGER + &command.DropTrigger{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + &CommandDrop{ + Target: 3, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // UPDATE + command.Update{ + UpdateOr: 0, + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Updates: []command.UpdateSetter{ + { + Cols: []string{ + "col1", + "col2", + }, + Value: command.ConstantBooleanExpr{ + Value: true, + }, + }, + }, + Filter: command.EqualityExpr{ + Left: command.LiteralExpr{ + Value: "leftLiteral", + }, + Right: command.LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + &Command_Update{ + UpdateOr: 0, + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Updates: []*UpdateSetter{ + { + Cols: []string{ + "col1", + "col2", + }, + Value: &UpdateSetter_Constant{ + Constant: &ConstantBooleanExpr{ + Value: true, + }, + }, + }, + }, + Filter: &Expr{ + Expr: &Expr_Equality{ + Equality: &EqualityExpr{ + Left: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "leftLiteral", + }, + }, + }, + Right: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + }, + }, + }, + }, + { + // JOIN + command.Join{ + Natural: true, + Type: 0, + Filter: command.FunctionExpr{ + Name: "function", + Distinct: true, + Args: []command.Expr{ + command.RangeExpr{ + Needle: command.LiteralExpr{ + Value: "literal", + }, + Lo: command.LiteralExpr{ + Value: "literal", + }, + Hi: command.LiteralExpr{ + Value: "literal", + }, + Invert: false, + }, + command.UnaryExpr{ + Operator: "operator", + Value: command.LiteralExpr{ + Value: "literal", + }, + }, + }, + }, + Left: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + Right: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + &Command_Join{ + Natural: true, + Type: 0, + Filter: &Expr{ + Expr: &Expr_Func{ + Func: &FunctionExpr{ + Name: "function", + Distinct: true, + Args: []*Expr{ + { + Expr: &Expr_Range{ + &RangeExpr{ + Needle: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Lo: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Hi: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Invert: false, + }, + }, + }, + { + Expr: &Expr_Unary{ + Unary: &UnaryExpr{ + Operator: "operator", + Value: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Left: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + Right: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + }, + { + // LIMIT + command.Limit{ + Limit: command.LiteralExpr{ + Value: "literal", + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + &Command_Limit{ + Limit: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + }, + { + // INSERT + command.Insert{ + InsertOr: 0, + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Cols: []command.Column{ + { + Table: "myTable1", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias2", + }, + }, + DefaultValues: false, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + &Command_Insert{ + InsertOr: 0, + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Cols: []*Column{ + { + Table: "myTable1", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias2", + }, + }, + DefaultValues: false, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + }, +} + +func TestConvertCommandToMessage(t *testing.T) { + for _, tt := range commandToMessageTests { + t.Run(tt.in.String(), func(t *testing.T) { + msg, _ := ConvertCommandToMessage(tt.in) + if !reflect.DeepEqual(msg, tt.out) { + t.Errorf("got %q, want %q", msg, tt.out) + } + }) + } +} + +var messageToCommandTests = []struct { + in Message + out command.Command +}{ + { + // SCAN + &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + { + // SELECT + &Command_Select{ + Filter: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + command.Select{ + Filter: command.LiteralExpr{ + Value: "literal", + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + { + // PROJECT + &Command_Project{ + Cols: []*Column{ + { + Table: "myTable1", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias2", + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + command.Project{ + Cols: []command.Column{ + { + Table: "myTable1", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias2", + }, + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + { + // DELETE + &Command_Delete{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Filter: &Expr{ + Expr: &Expr_Binary{ + Binary: &BinaryExpr{ + Operator: "operator", + Left: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "leftLiteral", + }, + }, + }, + Right: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + }, + }, + }, + command.Delete{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Filter: command.BinaryExpr{ + Operator: "operator", + Left: command.LiteralExpr{ + Value: "leftLiteral", + }, + Right: command.LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + { + // DROP TABLE + &CommandDrop{ + Target: 0, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + command.DropTable{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP VIEW + &CommandDrop{ + Target: 1, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + command.DropView{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP INDEX + &CommandDrop{ + Target: 2, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + command.DropIndex{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // DROP TRIGGER + &CommandDrop{ + Target: 3, + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + command.DropTrigger{ + IfExists: true, + Schema: "mySchema", + Name: "tableName", + }, + }, + { + // UPDATE + &Command_Update{ + UpdateOr: 0, + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Updates: []*UpdateSetter{ + { + Cols: []string{ + "col1", + "col2", + }, + Value: &UpdateSetter_Constant{ + Constant: &ConstantBooleanExpr{ + Value: true, + }, + }, + }, + }, + Filter: &Expr{ + Expr: &Expr_Equality{ + Equality: &EqualityExpr{ + Left: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "leftLiteral", + }, + }, + }, + Right: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + }, + }, + }, + command.Update{ + UpdateOr: 0, + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Updates: []command.UpdateSetter{ + { + Cols: []string{ + "col1", + "col2", + }, + Value: command.ConstantBooleanExpr{ + Value: true, + }, + }, + }, + Filter: command.EqualityExpr{ + Left: command.LiteralExpr{ + Value: "leftLiteral", + }, + Right: command.LiteralExpr{ + Value: "rightLiteral", + }, + }, + }, + }, + { + // JOIN + &Command_Join{ + Natural: true, + Type: 0, + Filter: &Expr{ + Expr: &Expr_Func{ + Func: &FunctionExpr{ + Name: "function", + Distinct: true, + Args: []*Expr{ + { + Expr: &Expr_Range{ + &RangeExpr{ + Needle: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Lo: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Hi: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Invert: false, + }, + }, + }, + { + Expr: &Expr_Unary{ + Unary: &UnaryExpr{ + Operator: "operator", + Value: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + Left: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + Right: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + command.Join{ + Natural: true, + Type: 0, + Filter: command.FunctionExpr{ + Name: "function", + Distinct: true, + Args: []command.Expr{ + command.RangeExpr{ + Needle: command.LiteralExpr{ + Value: "literal", + }, + Lo: command.LiteralExpr{ + Value: "literal", + }, + Hi: command.LiteralExpr{ + Value: "literal", + }, + Invert: false, + }, + command.UnaryExpr{ + Operator: "operator", + Value: command.LiteralExpr{ + Value: "literal", + }, + }, + }, + }, + Left: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + Right: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + { + // LIMIT + &Command_Limit{ + Limit: &Expr{ + Expr: &Expr_Literal{ + Literal: &LiteralExpr{ + Value: "literal", + }, + }, + }, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + command.Limit{ + Limit: command.LiteralExpr{ + Value: "literal", + }, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + { + // INSERT + &Command_Insert{ + InsertOr: 0, + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Cols: []*Column{ + { + Table: "myTable1", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: &Expr{ + Expr: &Expr_Literal{ + &LiteralExpr{ + Value: "literal", + }, + }, + }, + Alias: "myAlias2", + }, + }, + DefaultValues: false, + Input: &List{ + List: &List_Scan{ + Scan: &Command_Scan{ + Table: &SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, + }, + command.Insert{ + InsertOr: 0, + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + Cols: []command.Column{ + { + Table: "myTable1", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias1", + }, + { + Table: "myTable2", + Column: command.LiteralExpr{ + Value: "literal", + }, + Alias: "myAlias2", + }, + }, + DefaultValues: false, + Input: command.Scan{ + Table: &command.SimpleTable{ + Schema: "mySchema", + Table: "myTable", + Alias: "myAlias", + Indexed: true, + Index: "myIndex", + }, + }, + }, + }, +} + +func TestConvertMessageToCommand(t *testing.T) { + for _, tt := range messageToCommandTests { + t.Run(tt.in.Kind().String(), func(t *testing.T) { + msg := ConvertMessageToCommand(tt.in) + if !reflect.DeepEqual(msg, tt.out) { + t.Errorf("got %q, want %q", msg, tt.out) + } + }) + } +} diff --git a/internal/raft/message/doc.go b/internal/raft/message/doc.go new file mode 100644 index 00000000..b737b75b --- /dev/null +++ b/internal/raft/message/doc.go @@ -0,0 +1,22 @@ +// Package message implements messages used in the raft module for +// communication. Create a message by calling constructor functions. An example +// follows +// +// // need to create a request-vote-message and send it +// msg := message.NewRequestVoteRequest(term, candidate.ID(), lastLogIndex, lastLogTerm) // create the message +// data, err := message.Marshal(msg) // marshal it +// // handle err +// conn.Send(data) // sent it through the network +// +// When receiving data however, follow this example. In here, we will receive +// bytes, unmarshal them as a message, and then process the message. +// +// data := conn.Receive() +// msg, err := message.Unmarshal(data) +// switch msg.Kind() { +// case message.KindRequestVoteResponse: +// // process a request-vote-response +// default: +// panic("cannot handle the message") +// } +package message diff --git a/internal/raft/message/error.go b/internal/raft/message/error.go new file mode 100644 index 00000000..9ef506fa --- /dev/null +++ b/internal/raft/message/error.go @@ -0,0 +1,17 @@ +package message + +// Error is a helper type that allows constant errors. +type Error string + +func (e Error) Error() string { return string(e) } + +const ( + // ErrUnknownKind indicates that the kind of the message is not known to + // this implementation. + ErrUnknownKind Error = "unknown message kind" + // ErrUnknownCommandKind indicates that the kind of command is not known + // to this implemenatation. + ErrUnknownCommandKind Error = "unknown command kind" + // ErrNilCommand indicates that the command variable found is nil. + ErrNilCommand Error = "nil command found" +) diff --git a/internal/raft/message/follower_location_list.go b/internal/raft/message/follower_location_list.go new file mode 100644 index 00000000..e2333984 --- /dev/null +++ b/internal/raft/message/follower_location_list.go @@ -0,0 +1,30 @@ +package message + +//go:generate protoc --go_out=. follower_location_list.proto + +var _ Message = (*FollowerLocationListRequest)(nil) +var _ Message = (*FollowerLocationListResponse)(nil) + +// NewFollowerLocationListRequest creates a new follower-location-list-request +// message with the given parameters. +func NewFollowerLocationListRequest() *FollowerLocationListRequest { + return &FollowerLocationListRequest{} +} + +// Kind returns KindFollowerLocationListRequest. +func (*FollowerLocationListRequest) Kind() Kind { + return KindFollowerLocationListRequest +} + +// NewFollowerLocationListResponse creates a new follower-location-list-response +// message with the given parameters. +func NewFollowerLocationListResponse(followerLocations []string) *FollowerLocationListResponse { + return &FollowerLocationListResponse{ + FollowerAddress: followerLocations, + } +} + +// Kind returns KindFollowerLocationListResponse. +func (*FollowerLocationListResponse) Kind() Kind { + return KindFollowerLocationListResponse +} diff --git a/internal/raft/message/follower_location_list.pb.go b/internal/raft/message/follower_location_list.pb.go new file mode 100644 index 00000000..88264c2d --- /dev/null +++ b/internal/raft/message/follower_location_list.pb.go @@ -0,0 +1,205 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: follower_location_list.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type FollowerLocationListRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *FollowerLocationListRequest) Reset() { + *x = FollowerLocationListRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_follower_location_list_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FollowerLocationListRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FollowerLocationListRequest) ProtoMessage() {} + +func (x *FollowerLocationListRequest) ProtoReflect() protoreflect.Message { + mi := &file_follower_location_list_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FollowerLocationListRequest.ProtoReflect.Descriptor instead. +func (*FollowerLocationListRequest) Descriptor() ([]byte, []int) { + return file_follower_location_list_proto_rawDescGZIP(), []int{0} +} + +type FollowerLocationListResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FollowerAddress []string `protobuf:"bytes,1,rep,name=followerAddress,proto3" json:"followerAddress,omitempty"` +} + +func (x *FollowerLocationListResponse) Reset() { + *x = FollowerLocationListResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_follower_location_list_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FollowerLocationListResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FollowerLocationListResponse) ProtoMessage() {} + +func (x *FollowerLocationListResponse) ProtoReflect() protoreflect.Message { + mi := &file_follower_location_list_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FollowerLocationListResponse.ProtoReflect.Descriptor instead. +func (*FollowerLocationListResponse) Descriptor() ([]byte, []int) { + return file_follower_location_list_proto_rawDescGZIP(), []int{1} +} + +func (x *FollowerLocationListResponse) GetFollowerAddress() []string { + if x != nil { + return x.FollowerAddress + } + return nil +} + +var File_follower_location_list_proto protoreflect.FileDescriptor + +var file_follower_location_list_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x65, 0x72, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x48, 0x0a, 0x1c, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x72, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_follower_location_list_proto_rawDescOnce sync.Once + file_follower_location_list_proto_rawDescData = file_follower_location_list_proto_rawDesc +) + +func file_follower_location_list_proto_rawDescGZIP() []byte { + file_follower_location_list_proto_rawDescOnce.Do(func() { + file_follower_location_list_proto_rawDescData = protoimpl.X.CompressGZIP(file_follower_location_list_proto_rawDescData) + }) + return file_follower_location_list_proto_rawDescData +} + +var file_follower_location_list_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_follower_location_list_proto_goTypes = []interface{}{ + (*FollowerLocationListRequest)(nil), // 0: message.FollowerLocationListRequest + (*FollowerLocationListResponse)(nil), // 1: message.FollowerLocationListResponse +} +var file_follower_location_list_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_follower_location_list_proto_init() } +func file_follower_location_list_proto_init() { + if File_follower_location_list_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_follower_location_list_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FollowerLocationListRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_follower_location_list_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FollowerLocationListResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_follower_location_list_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_follower_location_list_proto_goTypes, + DependencyIndexes: file_follower_location_list_proto_depIdxs, + MessageInfos: file_follower_location_list_proto_msgTypes, + }.Build() + File_follower_location_list_proto = out.File + file_follower_location_list_proto_rawDesc = nil + file_follower_location_list_proto_goTypes = nil + file_follower_location_list_proto_depIdxs = nil +} diff --git a/internal/raft/message/follower_location_list.proto b/internal/raft/message/follower_location_list.proto new file mode 100644 index 00000000..5a80bbf3 --- /dev/null +++ b/internal/raft/message/follower_location_list.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; + +message FollowerLocationListRequest { +} + +message FollowerLocationListResponse { + repeated string followerAddress = 1; +} \ No newline at end of file diff --git a/internal/raft/message/kind.go b/internal/raft/message/kind.go new file mode 100644 index 00000000..eaeabcde --- /dev/null +++ b/internal/raft/message/kind.go @@ -0,0 +1,49 @@ +package message + +//go:generate stringer -type=Kind + +// Kind describes a kind of a message, that is used by the raft module. +type Kind uint32 + +// Available kinds +const ( + // KindUnknown must not be used. It is the default value for Kind. If this + // value occurs, something was not initialized properly. + KindUnknown Kind = iota + // KindTestMessage must not be used. It is used for tests only. + KindTestMessage + + KindAppendEntriesRequest + KindAppendEntriesResponse + + KindFollowerLocationListRequest + KindFollowerLocationListResponse + + KindLeaderLocationRequest + KindLeaderLocationResponse + + KindRequestVoteRequest + KindRequestVoteResponse + + KindLogAppendRequest + + KindCommand + KindCommandScan + KindCommandSelect + KindCommandProject + KindCommandDelete + KindCommandDrop + KindCommandUpdate + KindCommandJoin + KindCommandLimit + KindCommandInsert + + KindExpr + KindLiteralExpr + KindConstantBooleanExpr + KindUnaryExpr + KindBinaryExpr + KindFunctionExpr + KindEqualityExpr + KindRangeExpr +) diff --git a/internal/raft/message/kind_string.go b/internal/raft/message/kind_string.go new file mode 100644 index 00000000..0ad01c1a --- /dev/null +++ b/internal/raft/message/kind_string.go @@ -0,0 +1,51 @@ +// Code generated by "stringer -type=Kind"; DO NOT EDIT. + +package message + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[KindUnknown-0] + _ = x[KindTestMessage-1] + _ = x[KindAppendEntriesRequest-2] + _ = x[KindAppendEntriesResponse-3] + _ = x[KindFollowerLocationListRequest-4] + _ = x[KindFollowerLocationListResponse-5] + _ = x[KindLeaderLocationRequest-6] + _ = x[KindLeaderLocationResponse-7] + _ = x[KindRequestVoteRequest-8] + _ = x[KindRequestVoteResponse-9] + _ = x[KindLogAppendRequest-10] + _ = x[KindCommand-11] + _ = x[KindCommandScan-12] + _ = x[KindCommandSelect-13] + _ = x[KindCommandProject-14] + _ = x[KindCommandDelete-15] + _ = x[KindCommandDrop-16] + _ = x[KindCommandUpdate-17] + _ = x[KindCommandJoin-18] + _ = x[KindCommandLimit-19] + _ = x[KindCommandInsert-20] + _ = x[KindExpr-21] + _ = x[KindLiteralExpr-22] + _ = x[KindConstantBooleanExpr-23] + _ = x[KindUnaryExpr-24] + _ = x[KindBinaryExpr-25] + _ = x[KindFunctionExpr-26] + _ = x[KindEqualityExpr-27] + _ = x[KindRangeExpr-28] +} + +const _Kind_name = "KindUnknownKindTestMessageKindAppendEntriesRequestKindAppendEntriesResponseKindFollowerLocationListRequestKindFollowerLocationListResponseKindLeaderLocationRequestKindLeaderLocationResponseKindRequestVoteRequestKindRequestVoteResponseKindLogAppendRequestKindCommandKindCommandScanKindCommandSelectKindCommandProjectKindCommandDeleteKindCommandDropKindCommandUpdateKindCommandJoinKindCommandLimitKindCommandInsertKindExprKindLiteralExprKindConstantBooleanExprKindUnaryExprKindBinaryExprKindFunctionExprKindEqualityExprKindRangeExpr" + +var _Kind_index = [...]uint16{0, 11, 26, 50, 75, 106, 138, 163, 189, 211, 234, 254, 265, 280, 297, 315, 332, 347, 364, 379, 395, 412, 420, 435, 458, 471, 485, 501, 517, 530} + +func (i Kind) String() string { + if i >= Kind(len(_Kind_index)-1) { + return "Kind(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Kind_name[_Kind_index[i]:_Kind_index[i+1]] +} diff --git a/internal/raft/message/leader_location.go b/internal/raft/message/leader_location.go new file mode 100644 index 00000000..4ad31887 --- /dev/null +++ b/internal/raft/message/leader_location.go @@ -0,0 +1,30 @@ +package message + +//go:generate protoc --go_out=. leader_location.proto + +var _ Message = (*LeaderLocationRequest)(nil) +var _ Message = (*LeaderLocationResponse)(nil) + +// NewLeaderLocationRequest creates a new leader-location-request message with +// the given parameters. +func NewLeaderLocationRequest() *LeaderLocationRequest { + return &LeaderLocationRequest{} +} + +// Kind returns KindLeaderLocationRequest. +func (*LeaderLocationRequest) Kind() Kind { + return KindLeaderLocationRequest +} + +// NewLeaderLocationResponse creates a new leader-location-response message with +// the given parameters. +func NewLeaderLocationResponse(leaderAddress string) *LeaderLocationResponse { + return &LeaderLocationResponse{ + LeaderAddress: leaderAddress, + } +} + +// Kind returns KindLeaderLocationResponse. +func (*LeaderLocationResponse) Kind() Kind { + return KindLeaderLocationResponse +} diff --git a/internal/raft/message/leader_location.pb.go b/internal/raft/message/leader_location.pb.go new file mode 100644 index 00000000..452e0fed --- /dev/null +++ b/internal/raft/message/leader_location.pb.go @@ -0,0 +1,203 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: leader_location.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type LeaderLocationRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *LeaderLocationRequest) Reset() { + *x = LeaderLocationRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_leader_location_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaderLocationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaderLocationRequest) ProtoMessage() {} + +func (x *LeaderLocationRequest) ProtoReflect() protoreflect.Message { + mi := &file_leader_location_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LeaderLocationRequest.ProtoReflect.Descriptor instead. +func (*LeaderLocationRequest) Descriptor() ([]byte, []int) { + return file_leader_location_proto_rawDescGZIP(), []int{0} +} + +type LeaderLocationResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LeaderAddress string `protobuf:"bytes,1,opt,name=leaderAddress,proto3" json:"leaderAddress,omitempty"` +} + +func (x *LeaderLocationResponse) Reset() { + *x = LeaderLocationResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_leader_location_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaderLocationResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaderLocationResponse) ProtoMessage() {} + +func (x *LeaderLocationResponse) ProtoReflect() protoreflect.Message { + mi := &file_leader_location_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LeaderLocationResponse.ProtoReflect.Descriptor instead. +func (*LeaderLocationResponse) Descriptor() ([]byte, []int) { + return file_leader_location_proto_rawDescGZIP(), []int{1} +} + +func (x *LeaderLocationResponse) GetLeaderAddress() string { + if x != nil { + return x.LeaderAddress + } + return "" +} + +var File_leader_location_proto protoreflect.FileDescriptor + +var file_leader_location_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x22, 0x17, 0x0a, 0x15, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3e, 0x0a, 0x16, 0x4c, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_leader_location_proto_rawDescOnce sync.Once + file_leader_location_proto_rawDescData = file_leader_location_proto_rawDesc +) + +func file_leader_location_proto_rawDescGZIP() []byte { + file_leader_location_proto_rawDescOnce.Do(func() { + file_leader_location_proto_rawDescData = protoimpl.X.CompressGZIP(file_leader_location_proto_rawDescData) + }) + return file_leader_location_proto_rawDescData +} + +var file_leader_location_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_leader_location_proto_goTypes = []interface{}{ + (*LeaderLocationRequest)(nil), // 0: message.LeaderLocationRequest + (*LeaderLocationResponse)(nil), // 1: message.LeaderLocationResponse +} +var file_leader_location_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_leader_location_proto_init() } +func file_leader_location_proto_init() { + if File_leader_location_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_leader_location_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaderLocationRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_leader_location_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaderLocationResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_leader_location_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_leader_location_proto_goTypes, + DependencyIndexes: file_leader_location_proto_depIdxs, + MessageInfos: file_leader_location_proto_msgTypes, + }.Build() + File_leader_location_proto = out.File + file_leader_location_proto_rawDesc = nil + file_leader_location_proto_goTypes = nil + file_leader_location_proto_depIdxs = nil +} diff --git a/internal/raft/message/leader_location.proto b/internal/raft/message/leader_location.proto new file mode 100644 index 00000000..0cb11f3b --- /dev/null +++ b/internal/raft/message/leader_location.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; + +message LeaderLocationRequest { +} + +message LeaderLocationResponse { + string leaderAddress = 1; +} \ No newline at end of file diff --git a/internal/raft/message/log_append_request.go b/internal/raft/message/log_append_request.go new file mode 100644 index 00000000..5fec7f5f --- /dev/null +++ b/internal/raft/message/log_append_request.go @@ -0,0 +1,18 @@ +package message + +//go:generate protoc --go_out=. append_entries.proto + +var _ Message = (*AppendEntriesRequest)(nil) + +// NewLogAppendRequest creates a new append-entries-request message with the +// given parameters. +func NewLogAppendRequest(data *Command) *LogAppendRequest { + return &LogAppendRequest{ + Data: data, + } +} + +// Kind returns KindAppendEntriesResponse. +func (*LogAppendRequest) Kind() Kind { + return KindAppendEntriesResponse +} diff --git a/internal/raft/message/log_append_request.pb.go b/internal/raft/message/log_append_request.pb.go new file mode 100644 index 00000000..6ba4efee --- /dev/null +++ b/internal/raft/message/log_append_request.pb.go @@ -0,0 +1,155 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: log_append_request.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type LogAppendRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data *Command `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *LogAppendRequest) Reset() { + *x = LogAppendRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_log_append_request_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LogAppendRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LogAppendRequest) ProtoMessage() {} + +func (x *LogAppendRequest) ProtoReflect() protoreflect.Message { + mi := &file_log_append_request_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LogAppendRequest.ProtoReflect.Descriptor instead. +func (*LogAppendRequest) Descriptor() ([]byte, []int) { + return file_log_append_request_proto_rawDescGZIP(), []int{0} +} + +func (x *LogAppendRequest) GetData() *Command { + if x != nil { + return x.Data + } + return nil +} + +var File_log_append_request_proto protoreflect.FileDescriptor + +var file_log_append_request_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x6c, 0x6f, 0x67, 0x5f, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x5f, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x1a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0x38, 0x0a, 0x10, 0x4c, 0x6f, 0x67, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x0b, 0x5a, 0x09, + 0x2e, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_log_append_request_proto_rawDescOnce sync.Once + file_log_append_request_proto_rawDescData = file_log_append_request_proto_rawDesc +) + +func file_log_append_request_proto_rawDescGZIP() []byte { + file_log_append_request_proto_rawDescOnce.Do(func() { + file_log_append_request_proto_rawDescData = protoimpl.X.CompressGZIP(file_log_append_request_proto_rawDescData) + }) + return file_log_append_request_proto_rawDescData +} + +var file_log_append_request_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_log_append_request_proto_goTypes = []interface{}{ + (*LogAppendRequest)(nil), // 0: message.LogAppendRequest + (*Command)(nil), // 1: message.Command +} +var file_log_append_request_proto_depIdxs = []int32{ + 1, // 0: message.LogAppendRequest.data:type_name -> message.Command + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_log_append_request_proto_init() } +func file_log_append_request_proto_init() { + if File_log_append_request_proto != nil { + return + } + file_command_proto_init() + if !protoimpl.UnsafeEnabled { + file_log_append_request_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LogAppendRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_log_append_request_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_log_append_request_proto_goTypes, + DependencyIndexes: file_log_append_request_proto_depIdxs, + MessageInfos: file_log_append_request_proto_msgTypes, + }.Build() + File_log_append_request_proto = out.File + file_log_append_request_proto_rawDesc = nil + file_log_append_request_proto_goTypes = nil + file_log_append_request_proto_depIdxs = nil +} diff --git a/internal/raft/message/log_append_request.proto b/internal/raft/message/log_append_request.proto new file mode 100644 index 00000000..3ed0a136 --- /dev/null +++ b/internal/raft/message/log_append_request.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; +import "command.proto"; + +message LogAppendRequest { + Command data = 1; +} \ No newline at end of file diff --git a/internal/raft/message/message.go b/internal/raft/message/message.go new file mode 100644 index 00000000..a3be587e --- /dev/null +++ b/internal/raft/message/message.go @@ -0,0 +1,75 @@ +package message + +import ( + "bytes" + "encoding/binary" + "fmt" + + "google.golang.org/protobuf/proto" +) + +// Message describes a serializable, more or less self-describing protobuf +// message. A message consists of a kind (message.Kind) and an actual protobuf +// message. +type Message interface { + proto.Message + // Kind returns the kind of this message. If this returns + // message.KindUnknown, something went wrong, or the client and server + // versions are not matching. + Kind() Kind +} + +// Marshal converts the given message to a byte slice that can be unmarshalled +// with message.Unmarshal. The kind is encoded with 4 bytes big endian as uint32 +// and is the first 4 bytes of the serialized message. The rest of the message +// is the serialized protobuf message. +func Marshal(m Message) ([]byte, error) { + data, err := proto.Marshal(m) + if err != nil { + return nil, fmt.Errorf("proto marshal: %w", err) + } + + var buf bytes.Buffer + kind := make([]byte, 4) + binary.BigEndian.PutUint32(kind, uint32(m.Kind())) + buf.Write(kind) + buf.Write(data) + return buf.Bytes(), nil +} + +// Unmarshal converts bytes to a message. For using the returned message, check +// Message.Kind() and process a it accordingly. +func Unmarshal(data []byte) (Message, error) { + kindBytes := data[:4] // kind is uint32, which has 4 bytes + payload := data[4:] + + kind := Kind(binary.BigEndian.Uint32(kindBytes)) + var msg Message + switch kind { + case KindAppendEntriesRequest: + msg = &AppendEntriesRequest{} + case KindAppendEntriesResponse: + msg = &AppendEntriesResponse{} + case KindFollowerLocationListRequest: + msg = &FollowerLocationListRequest{} + case KindFollowerLocationListResponse: + msg = &FollowerLocationListResponse{} + case KindLeaderLocationRequest: + msg = &LeaderLocationRequest{} + case KindLeaderLocationResponse: + msg = &LeaderLocationResponse{} + case KindRequestVoteRequest: + msg = &RequestVoteRequest{} + case KindRequestVoteResponse: + msg = &RequestVoteResponse{} + case KindTestMessage: + msg = &TestMessage{} + default: + return nil, ErrUnknownKind + } + + if err := proto.Unmarshal(payload, msg); err != nil { + return nil, fmt.Errorf("unmarshal: %w", err) + } + return msg, nil +} diff --git a/internal/raft/message/request_vote.go b/internal/raft/message/request_vote.go new file mode 100644 index 00000000..1e2137c0 --- /dev/null +++ b/internal/raft/message/request_vote.go @@ -0,0 +1,38 @@ +package message + +import "github.com/tomarrell/lbadd/internal/id" + +//go:generate protoc --go_out=. request_vote.proto + +var _ Message = (*RequestVoteRequest)(nil) +var _ Message = (*RequestVoteResponse)(nil) + +// NewRequestVoteRequest creates a new request-vote-request message with the +// given parameters. +func NewRequestVoteRequest(term int32, candidateID id.ID, lastLogIndex int32, lastLogTerm int32) *RequestVoteRequest { + return &RequestVoteRequest{ + Term: term, + CandidateID: candidateID.Bytes(), + LastLogIndex: lastLogIndex, + LastLogTerm: lastLogTerm, + } +} + +// Kind returns KindRequestVoteRequest. +func (*RequestVoteRequest) Kind() Kind { + return KindRequestVoteRequest +} + +// NewRequestVoteResponse creates a new request-vote-response message with the +// given parameters. +func NewRequestVoteResponse(term int32, voteGranted bool) *RequestVoteResponse { + return &RequestVoteResponse{ + Term: term, + VoteGranted: voteGranted, + } +} + +// Kind returns KindRequestVoteResponse. +func (*RequestVoteResponse) Kind() Kind { + return KindRequestVoteResponse +} diff --git a/internal/raft/message/request_vote.pb.go b/internal/raft/message/request_vote.pb.go new file mode 100644 index 00000000..1ea44e62 --- /dev/null +++ b/internal/raft/message/request_vote.pb.go @@ -0,0 +1,253 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: request_vote.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type RequestVoteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + CandidateID []byte `protobuf:"bytes,2,opt,name=candidateID,proto3" json:"candidateID,omitempty"` + LastLogIndex int32 `protobuf:"varint,3,opt,name=lastLogIndex,proto3" json:"lastLogIndex,omitempty"` + LastLogTerm int32 `protobuf:"varint,4,opt,name=lastLogTerm,proto3" json:"lastLogTerm,omitempty"` +} + +func (x *RequestVoteRequest) Reset() { + *x = RequestVoteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_request_vote_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteRequest) ProtoMessage() {} + +func (x *RequestVoteRequest) ProtoReflect() protoreflect.Message { + mi := &file_request_vote_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteRequest.ProtoReflect.Descriptor instead. +func (*RequestVoteRequest) Descriptor() ([]byte, []int) { + return file_request_vote_proto_rawDescGZIP(), []int{0} +} + +func (x *RequestVoteRequest) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *RequestVoteRequest) GetCandidateID() []byte { + if x != nil { + return x.CandidateID + } + return nil +} + +func (x *RequestVoteRequest) GetLastLogIndex() int32 { + if x != nil { + return x.LastLogIndex + } + return 0 +} + +func (x *RequestVoteRequest) GetLastLogTerm() int32 { + if x != nil { + return x.LastLogTerm + } + return 0 +} + +type RequestVoteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Term int32 `protobuf:"varint,1,opt,name=term,proto3" json:"term,omitempty"` + VoteGranted bool `protobuf:"varint,2,opt,name=voteGranted,proto3" json:"voteGranted,omitempty"` +} + +func (x *RequestVoteResponse) Reset() { + *x = RequestVoteResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_request_vote_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RequestVoteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequestVoteResponse) ProtoMessage() {} + +func (x *RequestVoteResponse) ProtoReflect() protoreflect.Message { + mi := &file_request_vote_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequestVoteResponse.ProtoReflect.Descriptor instead. +func (*RequestVoteResponse) Descriptor() ([]byte, []int) { + return file_request_vote_proto_rawDescGZIP(), []int{1} +} + +func (x *RequestVoteResponse) GetTerm() int32 { + if x != nil { + return x.Term + } + return 0 +} + +func (x *RequestVoteResponse) GetVoteGranted() bool { + if x != nil { + return x.VoteGranted + } + return false +} + +var File_request_vote_proto protoreflect.FileDescriptor + +var file_request_vote_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x76, 0x6f, 0x74, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x90, 0x01, + 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x6e, 0x64, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, + 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x61, + 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, + 0x0a, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x67, 0x54, 0x65, 0x72, 0x6d, + 0x22, 0x4b, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x6f, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x65, 0x72, 0x6d, 0x12, 0x20, 0x0a, 0x0b, 0x76, + 0x6f, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x76, 0x6f, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x42, 0x0b, 0x5a, + 0x09, 0x2e, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_request_vote_proto_rawDescOnce sync.Once + file_request_vote_proto_rawDescData = file_request_vote_proto_rawDesc +) + +func file_request_vote_proto_rawDescGZIP() []byte { + file_request_vote_proto_rawDescOnce.Do(func() { + file_request_vote_proto_rawDescData = protoimpl.X.CompressGZIP(file_request_vote_proto_rawDescData) + }) + return file_request_vote_proto_rawDescData +} + +var file_request_vote_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_request_vote_proto_goTypes = []interface{}{ + (*RequestVoteRequest)(nil), // 0: message.RequestVoteRequest + (*RequestVoteResponse)(nil), // 1: message.RequestVoteResponse +} +var file_request_vote_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_request_vote_proto_init() } +func file_request_vote_proto_init() { + if File_request_vote_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_request_vote_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_request_vote_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestVoteResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_request_vote_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_request_vote_proto_goTypes, + DependencyIndexes: file_request_vote_proto_depIdxs, + MessageInfos: file_request_vote_proto_msgTypes, + }.Build() + File_request_vote_proto = out.File + file_request_vote_proto_rawDesc = nil + file_request_vote_proto_goTypes = nil + file_request_vote_proto_depIdxs = nil +} diff --git a/internal/raft/message/request_vote.proto b/internal/raft/message/request_vote.proto new file mode 100644 index 00000000..b973cf67 --- /dev/null +++ b/internal/raft/message/request_vote.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; + +message RequestVoteRequest { + int32 term = 1; + bytes candidateID = 2; + int32 lastLogIndex = 3; + int32 lastLogTerm = 4; +} + +message RequestVoteResponse { + int32 term = 1; + bool voteGranted = 2; +} \ No newline at end of file diff --git a/internal/raft/message/test_message.go b/internal/raft/message/test_message.go new file mode 100644 index 00000000..fcf501eb --- /dev/null +++ b/internal/raft/message/test_message.go @@ -0,0 +1,17 @@ +package message + +//go:generate protoc --go_out=. test_message.proto + +var _ Message = (*TestMessage)(nil) + +// NewTestMessage creates a new test message with the given data. +func NewTestMessage(data string) *TestMessage { + return &TestMessage{ + Data: data, + } +} + +// Kind returns KindTestMessage. +func (*TestMessage) Kind() Kind { + return KindTestMessage +} diff --git a/internal/raft/message/test_message.pb.go b/internal/raft/message/test_message.pb.go new file mode 100644 index 00000000..031323ea --- /dev/null +++ b/internal/raft/message/test_message.pb.go @@ -0,0 +1,149 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.22.0 +// protoc v3.11.4 +// source: test_message.proto + +//lint:file-ignore SA1019 Generated deprecated import + +package message + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type TestMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Data string `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *TestMessage) Reset() { + *x = TestMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_test_message_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestMessage) ProtoMessage() {} + +func (x *TestMessage) ProtoReflect() protoreflect.Message { + mi := &file_test_message_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestMessage.ProtoReflect.Descriptor instead. +func (*TestMessage) Descriptor() ([]byte, []int) { + return file_test_message_proto_rawDescGZIP(), []int{0} +} + +func (x *TestMessage) GetData() string { + if x != nil { + return x.Data + } + return "" +} + +var File_test_message_proto protoreflect.FileDescriptor + +var file_test_message_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x21, 0x0a, + 0x0b, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_test_message_proto_rawDescOnce sync.Once + file_test_message_proto_rawDescData = file_test_message_proto_rawDesc +) + +func file_test_message_proto_rawDescGZIP() []byte { + file_test_message_proto_rawDescOnce.Do(func() { + file_test_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_message_proto_rawDescData) + }) + return file_test_message_proto_rawDescData +} + +var file_test_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_test_message_proto_goTypes = []interface{}{ + (*TestMessage)(nil), // 0: message.TestMessage +} +var file_test_message_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_test_message_proto_init() } +func file_test_message_proto_init() { + if File_test_message_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_message_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_test_message_proto_goTypes, + DependencyIndexes: file_test_message_proto_depIdxs, + MessageInfos: file_test_message_proto_msgTypes, + }.Build() + File_test_message_proto = out.File + file_test_message_proto_rawDesc = nil + file_test_message_proto_goTypes = nil + file_test_message_proto_depIdxs = nil +} diff --git a/internal/raft/message/test_message.proto b/internal/raft/message/test_message.proto new file mode 100644 index 00000000..8b59dd2f --- /dev/null +++ b/internal/raft/message/test_message.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; + +//lint:file-ignore SA1019 Generated deprecated import + +package message; +option go_package = ".;message"; + +message TestMessage { + string data = 1; +} \ No newline at end of file diff --git a/internal/raft/mocks/cluster.go b/internal/raft/mocks/cluster.go new file mode 100644 index 00000000..66f9ea34 --- /dev/null +++ b/internal/raft/mocks/cluster.go @@ -0,0 +1,111 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + id "github.com/tomarrell/lbadd/internal/id" + message "github.com/tomarrell/lbadd/internal/raft/message" + + mock "github.com/stretchr/testify/mock" + + network "github.com/tomarrell/lbadd/internal/network" +) + +// Cluster is an autogenerated mock type for the Cluster type +type Cluster struct { + mock.Mock +} + +// Broadcast provides a mock function with given fields: _a0, _a1 +func (_m *Cluster) Broadcast(_a0 context.Context, _a1 message.Message) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, message.Message) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Close provides a mock function with given fields: +func (_m *Cluster) Close() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Nodes provides a mock function with given fields: +func (_m *Cluster) Nodes() []network.Conn { + ret := _m.Called() + + var r0 []network.Conn + if rf, ok := ret.Get(0).(func() []network.Conn); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]network.Conn) + } + } + + return r0 +} + +// OwnID provides a mock function with given fields: +func (_m *Cluster) OwnID() id.ID { + ret := _m.Called() + + var r0 id.ID + if rf, ok := ret.Get(0).(func() id.ID); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(id.ID) + } + } + + return r0 +} + +// Receive provides a mock function with given fields: _a0 +func (_m *Cluster) Receive(_a0 context.Context) (network.Conn, message.Message, error) { + ret := _m.Called(_a0) + + var r0 network.Conn + if rf, ok := ret.Get(0).(func(context.Context) network.Conn); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(network.Conn) + } + } + + var r1 message.Message + if rf, ok := ret.Get(1).(func(context.Context) message.Message); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(message.Message) + } + } + + var r2 error + if rf, ok := ret.Get(2).(func(context.Context) error); ok { + r2 = rf(_a0) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} diff --git a/internal/raft/mocks/doc.go b/internal/raft/mocks/doc.go new file mode 100644 index 00000000..35abed3d --- /dev/null +++ b/internal/raft/mocks/doc.go @@ -0,0 +1,2 @@ +// Package mocks provides generated mock implementations for easy testing. +package mocks diff --git a/internal/raft/raft.go b/internal/raft/raft.go new file mode 100644 index 00000000..e39cb75f --- /dev/null +++ b/internal/raft/raft.go @@ -0,0 +1,337 @@ +package raft + +import ( + "context" + "io" + "math/rand" + "sync" + "time" + + "github.com/rs/zerolog" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// Server is a description of a raft server. +type Server interface { + Start(context.Context) error + OnReplication(ReplicationHandler) + Input(*message.Command) + io.Closer +} + +// ReplicationHandler is a handler setter. +// It takes in the log entries as a string and returns the number +// of succeeded application of entries. +type ReplicationHandler func([]*message.Command) int + +// Node describes the current state of a raft node. +// The raft paper describes this as a "State" but node +// seemed more intuitive. +type Node struct { + State string + log zerolog.Logger + + PersistentState *PersistentState + VolatileState *VolatileState + VolatileStateLeader *VolatileStateLeader +} + +// PersistentState describes the persistent state data on a raft node. +type PersistentState struct { + CurrentTerm int32 + VotedFor id.ID // VotedFor is nil at init, and id.ID of the node after voting is complete. + Log []*message.LogData + + SelfID id.ID + LeaderID id.ID // LeaderID is nil at init, and the ID of the node after the leader is elected. + PeerIPs []network.Conn // PeerIPs has the connection variables of all the other nodes in the cluster. + ConnIDMap map[id.ID]int // ConnIDMap has a mapping of the ID of the server to its connection. + mu sync.Mutex +} + +// VolatileState describes the volatile state data on a raft node. +type VolatileState struct { + CommitIndex int32 + LastApplied int32 +} + +// VolatileStateLeader describes the volatile state data that exists on a raft leader. +type VolatileStateLeader struct { + NextIndex []int // Holds the nextIndex value for each of the followers in the cluster. + MatchIndex []int // Holds the matchIndex value for each of the followers in the cluster. +} + +var _ Server = (*SimpleServer)(nil) + +// SimpleServer implements a server in a cluster. +type SimpleServer struct { + node *Node + cluster Cluster + onReplication ReplicationHandler + log zerolog.Logger + timeoutProvider func(*Node) *time.Timer + lock sync.Mutex + + onRequestVotes func(*message.RequestVoteRequest) + onLeaderElected func() + onAppendEntries func() + onCompleteOneRound func() +} + +// incomingData describes every request that the server gets. +type incomingData struct { + conn network.Conn + msg message.Message +} + +// NewServer enables starting a raft server/cluster. +func NewServer(log zerolog.Logger, cluster Cluster) *SimpleServer { + return newServer(log, cluster, nil) +} + +func newServer(log zerolog.Logger, cluster Cluster, timeoutProvider func(*Node) *time.Timer) *SimpleServer { + if timeoutProvider == nil { + timeoutProvider = randomTimer + } + return &SimpleServer{ + log: log.With().Str("component", "raft").Logger(), + cluster: cluster, + timeoutProvider: timeoutProvider, + } +} + +// NewRaftNode initialises a raft cluster with the given configuration. +func NewRaftNode(cluster Cluster) *Node { + var nextIndex, matchIndex []int + + for range cluster.Nodes() { + nextIndex = append(nextIndex, -1) + matchIndex = append(matchIndex, -1) + } + connIDMap := make(map[id.ID]int) + for i := range cluster.Nodes() { + connIDMap[cluster.Nodes()[i].RemoteID()] = i + } + node := &Node{ + State: StateCandidate.String(), + PersistentState: &PersistentState{ + CurrentTerm: 0, + VotedFor: nil, + SelfID: cluster.OwnID(), + PeerIPs: cluster.Nodes(), + ConnIDMap: connIDMap, + }, + VolatileState: &VolatileState{ + CommitIndex: -1, + LastApplied: -1, + }, + VolatileStateLeader: &VolatileStateLeader{ + NextIndex: nextIndex, + MatchIndex: matchIndex, + }, + } + return node +} + +// Start starts a single raft node into beginning raft operations. +// This function starts the leader election and keeps a check on whether +// regular heartbeats to the node exists. It restarts leader election on failure to do so. +// This function also continuously listens on all the connections to the nodes +// and routes the requests to appropriate functions. +func (s *SimpleServer) Start(ctx context.Context) (err error) { + // Making the function idempotent, returns whether the server is already open. + s.lock.Lock() + if s.node != nil { + s.log.Debug(). + Str("self-id", s.node.PersistentState.SelfID.String()). + Msg("already open") + return network.ErrOpen + } + // Initialise all raft variables in this node. + node := NewRaftNode(s.cluster) + node.PersistentState.mu.Lock() + node.log = s.log + s.node = node + s.lock.Unlock() + selfID := node.PersistentState.SelfID + node.PersistentState.mu.Unlock() + + // liveChan is a channel that passes the incomingData once received. + liveChan := make(chan *incomingData) + // Listen forever on all node connections. + go func() { + for { + // Parallely start waiting for incoming data. + conn, msg, err := s.cluster.Receive(ctx) + if err != nil { + return + } + if msg != nil { + node.log. + Debug(). + Str("self-id", selfID.String()). + Str("received", msg.Kind().String()). + Msg("received request") + liveChan <- &incomingData{ + conn, + msg, + } + } + } + }() + + // This block of code checks what kind of request has to be serviced + // and calls the necessary function to complete it. + + for { + // If any sort of request (heartbeat,appendEntries,requestVote) + // isn't received by the server(node) it restarts leader election. + select { + case <-s.timeoutProvider(node).C: + s.lock.Lock() + if s.node == nil { + return + } + s.lock.Unlock() + // One round is said to be complete when leader election + // is started for all terms except the first term. + if s.node.PersistentState.CurrentTerm != 1 && s.onCompleteOneRound != nil { + s.onCompleteOneRound() + } + s.StartElection(ctx) + case data := <-liveChan: + err = s.processIncomingData(data) + if err != nil { + return + } + case <-ctx.Done(): + return + } + } +} + +// OnReplication is a handler setter. +func (s *SimpleServer) OnReplication(handler ReplicationHandler) { + s.onReplication = handler +} + +// Input appends the input log into the leaders log, only if the current node is the leader. +// If this was not a leader, the leaders data is communicated to the client. +func (s *SimpleServer) Input(input *message.Command) { + s.node.PersistentState.mu.Lock() + defer s.node.PersistentState.mu.Unlock() + + if s.node.State == StateLeader.String() { + logData := message.NewLogData(s.node.PersistentState.CurrentTerm, input) + s.node.PersistentState.Log = append(s.node.PersistentState.Log, logData) + } else { + // Relay data to leader. + logAppendRequest := message.NewLogAppendRequest(input) + + s.relayDataToServer(logAppendRequest) + } +} + +// Close closes the node and returns an error on failure. +func (s *SimpleServer) Close() error { + s.lock.Lock() + // Maintaining idempotency of the close function. + if s.node == nil { + return network.ErrClosed + } + s.node. + log. + Debug(). + Str("self-id", s.node.PersistentState.SelfID.String()). + Msg("closing node") + + s.node = nil + err := s.cluster.Close() + s.lock.Unlock() + return err +} + +// randomTimer returns tickers ranging from 150ms to 300ms. +func randomTimer(node *Node) *time.Timer { + randomInt := rand.Intn(150) + 150 + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Int("random timer set to", randomInt). + Msg("heart beat timer") + ticker := time.NewTimer(time.Duration(randomInt) * time.Millisecond) + return ticker +} + +// processIncomingData is responsible for parsing the incoming data and calling +// appropriate functions based on the request type. +func (s *SimpleServer) processIncomingData(data *incomingData) error { + + ctx := context.TODO() + + switch data.msg.Kind() { + case message.KindRequestVoteRequest: + requestVoteRequest := data.msg.(*message.RequestVoteRequest) + requestVoteResponse := s.node.RequestVoteResponse(requestVoteRequest) + payload, err := message.Marshal(requestVoteResponse) + if err != nil { + return err + } + err = data.conn.Send(ctx, payload) + if err != nil { + return err + } + case message.KindAppendEntriesRequest: + + appendEntriesRequest := data.msg.(*message.AppendEntriesRequest) + appendEntriesResponse := s.AppendEntriesResponse(appendEntriesRequest) + payload, err := message.Marshal(appendEntriesResponse) + if err != nil { + return err + } + err = data.conn.Send(ctx, payload) + if err != nil { + return err + } + // When the leader gets a forwarded append input message from one of it's followers. + case message.KindLogAppendRequest: + logAppendRequest := data.msg.(*message.LogAppendRequest) + input := logAppendRequest.Data + logData := message.NewLogData(s.node.PersistentState.CurrentTerm, input) + s.node.PersistentState.Log = append(s.node.PersistentState.Log, logData) + } + return nil +} + +// relayDataToServer sends the input log from the follower to a leader node. +// TODO: Figure out what to do with the errors generated here. +func (s *SimpleServer) relayDataToServer(req *message.LogAppendRequest) { + ctx := context.Background() + + payload, _ := message.Marshal(req) + + leaderNodeConn := s.cluster.Nodes()[s.node.PersistentState.ConnIDMap[s.node.PersistentState.LeaderID]] + _ = leaderNodeConn.Send(ctx, payload) +} + +// OnRequestVotes is a hook setter for RequestVotesRequest. +func (s *SimpleServer) OnRequestVotes(hook func(*message.RequestVoteRequest)) { + s.onRequestVotes = hook +} + +// OnLeaderElected is a hook setter for LeadeElectedRequest. +func (s *SimpleServer) OnLeaderElected(hook func()) { + s.onLeaderElected = hook +} + +// OnAppendEntries is a hook setter for AppenEntriesRequest. +func (s *SimpleServer) OnAppendEntries(hook func()) { + s.onAppendEntries = hook +} + +// OnCompleteOneRound is a hook setter for completion for one round of raft. +func (s *SimpleServer) OnCompleteOneRound(hook func()) { + s.onCompleteOneRound = hook +} diff --git a/internal/raft/raft_test.go b/internal/raft/raft_test.go new file mode 100644 index 00000000..cb4161f0 --- /dev/null +++ b/internal/raft/raft_test.go @@ -0,0 +1,168 @@ +package raft + +import ( + "context" + "os" + "testing" + "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/tomarrell/lbadd/internal/compiler/command" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + networkmocks "github.com/tomarrell/lbadd/internal/network/mocks" + "github.com/tomarrell/lbadd/internal/raft/cluster" + "github.com/tomarrell/lbadd/internal/raft/message" + raftmocks "github.com/tomarrell/lbadd/internal/raft/mocks" +) + +// Test_Raft tests the entire raft operation. +func Test_Raft(t *testing.T) { + + assert := assert.New(t) + ctx := context.Background() + + log := zerolog.New(os.Stdout).With().Logger().Level(zerolog.GlobalLevel()) + + // Create a new cluster. + cluster := new(raftmocks.Cluster) + clusterID := id.Create() + + // Mock 4 other nodes in the cluster. + conn1 := new(networkmocks.Conn) + conn2 := new(networkmocks.Conn) + conn3 := new(networkmocks.Conn) + conn4 := new(networkmocks.Conn) + + connSlice := []network.Conn{ + conn1, + conn2, + conn3, + conn4, + } + + conn1 = addRemoteID(conn1) + conn2 = addRemoteID(conn2) + conn3 = addRemoteID(conn3) + conn4 = addRemoteID(conn4) + + conn1.On("Send", ctx, mock.IsType([]byte{})).Return(nil) + conn2.On("Send", ctx, mock.IsType([]byte{})).Return(nil) + conn3.On("Send", ctx, mock.IsType([]byte{})).Return(nil) + conn4.On("Send", ctx, mock.IsType([]byte{})).Return(nil) + + reqVRes1 := message.NewRequestVoteResponse(1, true) + payload1, err := message.Marshal(reqVRes1) + assert.NoError(err) + + conn1.On("Receive", ctx).Return(payload1, nil).Once() + conn2.On("Receive", ctx).Return(payload1, nil).Once() + conn3.On("Receive", ctx).Return(payload1, nil).Once() + conn4.On("Receive", ctx).Return(payload1, nil).Once() + + appERes1 := message.NewAppendEntriesResponse(1, true) + payload2, err := message.Marshal(appERes1) + assert.NoError(err) + + conn1.On("Receive", ctx).Return(payload2, nil) + conn2.On("Receive", ctx).Return(payload2, nil) + conn3.On("Receive", ctx).Return(payload2, nil) + conn4.On("Receive", ctx).Return(payload2, nil) + + // set up cluster to return the slice of connections on demand. + cluster. + On("Nodes"). + Return(connSlice) + + // return cluster ID + cluster. + On("OwnID"). + Return(clusterID) + + cluster. + On("Receive", ctx). + Return(conn1, nil, nil).After(time.Duration(1000) * time.Second) + + cluster.On("Close").Return(nil) + + server := newServer( + log, + cluster, + timeoutProvider, + ) + + server.OnRequestVotes(func(msg *message.RequestVoteRequest) {}) + server.OnLeaderElected(func() {}) + server.OnAppendEntries(func() { + err = server.Close() + if err != network.ErrClosed { + assert.NoError(err) + } + }) + err = server.Start(ctx) + assert.NoError(err) +} + +func addRemoteID(conn *networkmocks.Conn) *networkmocks.Conn { + cID := id.Create() + conn.On("RemoteID").Return(cID) + return conn +} + +func timeoutProvider(node *Node) *time.Timer { + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Int("random timer set to", 150). + Msg("heart beat timer") + return time.NewTimer(time.Duration(150) * time.Millisecond) +} + +func Test_Integration(t *testing.T) { + log := zerolog.New(os.Stdout).With().Logger().Level(zerolog.GlobalLevel()) + + assert := assert.New(t) + operations := []OpData{ + { + Op: SendData, + Data: &OpSendData{ + Data: []*command.Command{}, + }, + }, + { + Op: StopNode, + Data: &OpStopNode{}, + }, + } + opParams := OperationParameters{ + Rounds: 4, + TimeLimit: 5, + Operations: operations, + } + + testNetwork, err := cluster.NewTestNetwork(5, log) + assert.Nil(err) + // for i := range testNetwork.Clusters { + // fmt.Printf("Cluster: %v\n", testNetwork.Clusters[i].Cluster) + // for j := range testNetwork.Clusters[i].Nodes { + // fmt.Printf("Node: %v\n", testNetwork.Clusters[i].Nodes[j]) + // } + // } + + cfg := NetworkConfiguration{} + ctx := context.Background() + ctx, cancelFunc := context.WithCancel(ctx) + + raftNodes := createRaftNodes(log, testNetwork) + + raftTest := NewSimpleRaftTest(log, opParams, cfg, raftNodes, cancelFunc) + + go func() { + err := raftTest.BeginTest(ctx) + assert.Nil(err) + }() + + <-time.After(time.Duration(opParams.TimeLimit) * time.Second) +} diff --git a/internal/raft/raft_test_framework.go b/internal/raft/raft_test_framework.go new file mode 100644 index 00000000..6d267c5c --- /dev/null +++ b/internal/raft/raft_test_framework.go @@ -0,0 +1,262 @@ +package raft + +import ( + "context" + "sync" + "time" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "github.com/tomarrell/lbadd/internal/raft/cluster" +) + +// Usage of framework: +// +// * Create a new instance of the RaftTestFramework; +// this begins the raft cluster and all operations. +// +// raftTest := NewSimpleRaftTest(log,opParams,cfg) +// +// * Use "InjectOperation" with appropriate args to +// trigger an operation in the cluster. +var _ TestFramework = (*SimpleRaftTest)(nil) + +// SimpleRaftTest implements TestFramework. +type SimpleRaftTest struct { + log zerolog.Logger + parameters OperationParameters + config NetworkConfiguration + raftNodes []*SimpleServer + + opChannel chan OpData + execChannel chan OpData + roundsChan chan bool + opQueue []OpData + round int + shutdown chan bool + mu sync.Mutex + cancelFunc context.CancelFunc +} + +// NewSimpleRaftTest provides a ready to use raft test framework. +func NewSimpleRaftTest( + log zerolog.Logger, + parameters OperationParameters, + config NetworkConfiguration, + raftNodes []*SimpleServer, + cancel context.CancelFunc, +) *SimpleRaftTest { + opChan := make(chan OpData, len(parameters.Operations)) + execChan := make(chan OpData, len(parameters.Operations)) + shutdownChan := make(chan bool, 4) + roundsChan := make(chan bool, 4) + return &SimpleRaftTest{ + log: log, + parameters: parameters, + config: config, + raftNodes: raftNodes, + opChannel: opChan, + execChannel: execChan, + roundsChan: roundsChan, + opQueue: []OpData{}, + round: 0, + shutdown: shutdownChan, + cancelFunc: cancel, + } +} + +// OpParams returns the parameters of operations of the test. +func (t *SimpleRaftTest) OpParams() OperationParameters { + return t.parameters +} + +// Config returns the configuration under which the test is running. +func (t *SimpleRaftTest) Config() NetworkConfiguration { + return t.config +} + +// BeginTest starts all the cluster operations by creating and +// starting the cluster and the nodes. This operation will be +// completely stable and allows failing of servers underneath +// while monitoring their behavior. +// +// BeginTest will wrapped under a Go Test for ease of use. +func (t *SimpleRaftTest) BeginTest(ctx context.Context) error { + // if t.config.IDs == nil && t.config.IPs == nil { + // return errors.New("nil network configuration") + // } + + // start up the raft operation. + for i := range t.raftNodes { + go func(i int) { + t.raftNodes[i].OnCompleteOneRound(t.roundHook) + _ = t.raftNodes[i].Start(ctx) + }(i) + } + + shutDownTimer := time.NewTimer(time.Duration(t.OpParams().TimeLimit) * time.Second) + + // start the execution goroutine. + log.Debug().Msg("beginning execution goroutine") + go t.executeOperation() + + log.Debug().Msg("initiating operation injection") + go t.pushOperations() + + // Look for incoming operations and parallely run them + // while waiting for the limit of the execution. + // Once the limit of the execution is reached, wait for + // all operations to finish and end the test. + for { + select { + case data := <-t.opChannel: + log.Debug(). + Str("executing", string(data.Op)). + Msg("beginning execution") + go t.execute(data) + case <-shutDownTimer.C: + log.Debug(). + Msg("shutting down - reached time limit") + return t.GracefulShutdown() + case <-t.roundsChan: + log.Debug(). + Msg("shutting down - reached round limit") + return t.GracefulShutdown() + } + } +} + +// GracefulShutdown shuts down all operations of the server after waiting +// all running operations to complete while not accepting any more op reqs. +func (t *SimpleRaftTest) GracefulShutdown() error { + t.cancelFunc() + var errSlice multiError + var errLock sync.Mutex + for i := range t.raftNodes { + err := t.raftNodes[i].Close() + if err != nil { + errLock.Lock() + errSlice = append(errSlice, err) + errLock.Unlock() + } + } + if len(errSlice) != 0 { + return errSlice + } + + t.shutdown <- true + log.Debug(). + Msg("gracefully shutting down") + return nil +} + +// InjectOperation initiates an operation in the raft cluster based on the args. +func (t *SimpleRaftTest) InjectOperation(op Operation, args interface{}) { + opData := OpData{ + Op: op, + Data: args, + } + log.Debug().Msg("injecting operation") + t.opChannel <- opData +} + +// pushOperations pushes operations into the execution queue. +func (t *SimpleRaftTest) pushOperations() { + for i := range t.parameters.Operations { + t.opChannel <- t.parameters.Operations[i] + } +} + +// execute appends the operation to the queue which will +// be cleared in definite intervals. +func (t *SimpleRaftTest) execute(opData OpData) { + log.Debug().Msg("operation moved to execution channel") + t.execChannel <- opData +} + +// executeOperation is always ready to run an incoming operation. +// It looks for the shutdown signal from the hook channel and +// shutdown by not allowing further operations to execute. +// +// When both cases of the select statement recieve a signal, +// select chooses one at random. This doesn't affect the operation +// as the execution will shutdown right after that operation is +// completed. +func (t *SimpleRaftTest) executeOperation() { + for { + select { + case <-t.shutdown: + log.Debug().Msg("execution shutting down") + return + case operation := <-t.execChannel: + log.Debug().Msg("executing operation") + switch operation.Op { + case SendData: + d := operation.Data.(*OpSendData) + t.SendData(d) + case StopNode: + d := operation.Data.(*OpStopNode) + t.StopNode(d) + case PartitionNetwork: + d := operation.Data.(*OpPartitionNetwork) + t.PartitionNetwork(d) + case RestartNode: + d := operation.Data.(*OpRestartNode) + t.RestartNode(d) + } + } + } +} + +func (t *SimpleRaftTest) roundHook() { + t.mu.Lock() + defer t.mu.Unlock() + t.round++ + if t.round == t.parameters.Rounds*len(t.raftNodes) { + t.roundsChan <- true + } +} + +// SendData sends command data to the cluster by calling +// the appropriate function in the raft module. +func (t *SimpleRaftTest) SendData(d *OpSendData) { + +} + +// StopNode stops the given node in the network. +// This is a test of robustness in the system to recover from +// a failure of a node. +// +// The implementation can involve killing/stopping the +// respective node. +func (t *SimpleRaftTest) StopNode(d *OpStopNode) { + +} + +// PartitionNetwork partitions the network into one or more +// groups as dictated by the arguments. This means that the +// nodes in different groups cannot communicate with the +// nodes in a different group. +// +// The implementation can involve removing the nodes in the +// in the respective "cluster" variable so that they are no +// longer available to access it. +func (t *SimpleRaftTest) PartitionNetwork(d *OpPartitionNetwork) { + +} + +// RestartNode restarts a previously stopped node which has +// all resources allocated to it but went down for any reason. +func (t *SimpleRaftTest) RestartNode(d *OpRestartNode) { + +} + +func createRaftNodes(log zerolog.Logger, cluster *cluster.TestNetwork) []*SimpleServer { + raftNodes := []*SimpleServer{} + for i := range cluster.Clusters { + node := NewServer(log, cluster.Clusters[i].Cluster) + raftNodes = append(raftNodes, node) + } + + return raftNodes +} diff --git a/internal/raft/request_votes.go b/internal/raft/request_votes.go new file mode 100644 index 00000000..0e0dc5ca --- /dev/null +++ b/internal/raft/request_votes.go @@ -0,0 +1,82 @@ +package raft + +import ( + "context" + "fmt" + + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" + "github.com/tomarrell/lbadd/internal/raft/message" +) + +// RequestVote enables a node to send out the RequestVotes RPC. +// This function requests a vote from one node and returns that node's response. +// It opens a connection to the intended node using the network layer and waits for a response. +func (s *SimpleServer) RequestVote(ctx context.Context, nodeConn network.Conn, req *message.RequestVoteRequest) (*message.RequestVoteResponse, error) { + + payload, err := message.Marshal(req) + if err != nil { + return nil, err + } + + err = nodeConn.Send(ctx, payload) + if err != nil { + return nil, err + } + + if s.onRequestVotes != nil { + s.onRequestVotes(req) + } + + res, err := nodeConn.Receive(ctx) + if err != nil { + return nil, err + } + + msg, err := message.Unmarshal(res) + if err != nil { + return nil, err + } + + return msg.(*message.RequestVoteResponse), nil +} + +// RequestVoteResponse function is called on a request from a candidate for a vote. This function +// generates the response for the responder node to send back to the candidate node. +func (node *Node) RequestVoteResponse(req *message.RequestVoteRequest) *message.RequestVoteResponse { + node.PersistentState.mu.Lock() + defer node.PersistentState.mu.Unlock() + + // If the candidate is not up to date with the term, reject the vote. + if req.Term < node.PersistentState.CurrentTerm { + return &message.RequestVoteResponse{ + Term: node.PersistentState.CurrentTerm, + VoteGranted: false, + } + } + + // If this node hasn't voted for any other node, vote only then. + // TODO: Check whether candidate's log is atleast as up to date as mine only then grant vote. + if node.PersistentState.VotedFor == nil { + cID, err := id.Parse(req.CandidateID) + if err != nil { + // no point in handling this because I really need that to parse into ID. + fmt.Println(err) + } + node.PersistentState.VotedFor = cID + node.log. + Debug(). + Str("self-id", node.PersistentState.SelfID.String()). + Str("vote granted to", cID.String()). + Msg("voting a peer") + return &message.RequestVoteResponse{ + Term: node.PersistentState.CurrentTerm, + VoteGranted: true, + } + } + + return &message.RequestVoteResponse{ + Term: node.PersistentState.CurrentTerm, + VoteGranted: false, + } +} diff --git a/internal/raft/simple_test.go b/internal/raft/simple_test.go new file mode 100644 index 00000000..695db1bf --- /dev/null +++ b/internal/raft/simple_test.go @@ -0,0 +1 @@ +package raft diff --git a/internal/raft/state.go b/internal/raft/state.go new file mode 100644 index 00000000..5aaec736 --- /dev/null +++ b/internal/raft/state.go @@ -0,0 +1,14 @@ +package raft + +//go:generate stringer -type=State + +// State is a raft state that a node can be in. +type State uint8 + +// Available states +const ( + StateUnknown State = iota + StateLeader + StateCandidate + StateFollower +) diff --git a/internal/raft/state_string.go b/internal/raft/state_string.go new file mode 100644 index 00000000..a478845f --- /dev/null +++ b/internal/raft/state_string.go @@ -0,0 +1,26 @@ +// Code generated by "stringer -type=State"; DO NOT EDIT. + +package raft + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[StateUnknown-0] + _ = x[StateLeader-1] + _ = x[StateCandidate-2] + _ = x[StateFollower-3] +} + +const _State_name = "StateUnknownStateLeaderStateCandidateStateFollower" + +var _State_index = [...]uint8{0, 12, 23, 37, 50} + +func (i State) String() string { + if i >= State(len(_State_index)-1) { + return "State(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _State_name[_State_index[i]:_State_index[i+1]] +} diff --git a/internal/raft/test_framework.go b/internal/raft/test_framework.go new file mode 100644 index 00000000..576ae721 --- /dev/null +++ b/internal/raft/test_framework.go @@ -0,0 +1,97 @@ +package raft + +import ( + "context" + + "github.com/tomarrell/lbadd/internal/compiler/command" + "github.com/tomarrell/lbadd/internal/id" + "github.com/tomarrell/lbadd/internal/network" +) + +// TestFramework describes a testing framework for creating +// a complete integration testing of the different modules of a +// raft implementation. +// +// The framework allows injecting mutiple types of operations, like, +// stopping a node, partitioning the cluster, adding an entry to the log +// of the cluster whilst allowing to monitor the operations of the cluster. +// +// The framework will be completely stable and run obeying the Operation +// parameters while running the cluster operations and logging their behaviour. +type TestFramework interface { + // OpParams provides the parameters for operation of the raft cluster. + OpParams() OperationParameters + // Cfg provides the network configuration of the cluster. + Config() NetworkConfiguration + // BeginTest kicks of all operations by starting the raft cluster. + // It obeys the parameters of operation and raises an error if the + // conditions for the test don't satisfy. + BeginTest(context.Context) error + // InjectOperation will initiate the given operation in the cluster. + InjectOperation(op Operation, args interface{}) + // GracefulShutdown ensures the cluster is shutdown by waiting for + // all the running operations to complete. + GracefulShutdown() error +} + +// OperationParameters are the bounds which dictate the parameters +// for the running integration test. +// +// The raft operation will run until it reaches the first of the two bounds. +// If the operation is in consensus in the first round, the TimeLimit variable +// will stop the operation once it's reached. +// +// All operations will be stopped gracefully whenever possible after the bounds +// are reached. +type OperationParameters struct { + // Rounds specifies how many rounds the raft operation must proceed until. + Rounds int + // TimeLimit specifies the limit until which the raft operation will run. + TimeLimit int + // Operations are all the operations that wil be performed in the test + Operations []OpData +} + +// NetworkConfiguration holds the details of the network of the cluster. +type NetworkConfiguration struct { + IPs []network.Conn + IDs []id.ID +} + +// Operation describes the different types of operations that can be performed on the cluster. +type Operation int + +// Types of Operations. +const ( + SendData Operation = 1 + iota + StopNode + PartitionNetwork + RestartNode +) + +// OpData fully describes a runnable operation on the raft cluster. +// The "data" field can be either of the data related to the operation. +type OpData struct { + Op Operation + Data interface{} +} + +// OpSendData describes the data related to SendData. +type OpSendData struct { + Data []*command.Command +} + +// OpStopNode describes the data related to StopNode. +type OpStopNode struct { + NodeID id.ID +} + +// OpPartitionNetwork describes the data related to PartitionNetwork. +type OpPartitionNetwork struct { + Groups [][]id.ID +} + +// OpRestartNode describes the data related to RestartNode. +type OpRestartNode struct { + NodeID id.ID +} diff --git a/internal/tool/analysis/ctxfunc/ctxfunc.go b/internal/tool/analysis/ctxfunc/ctxfunc.go index e3827539..57e2e6a3 100644 --- a/internal/tool/analysis/ctxfunc/ctxfunc.go +++ b/internal/tool/analysis/ctxfunc/ctxfunc.go @@ -5,6 +5,7 @@ package ctxfunc import ( "go/ast" "go/types" + "strings" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -26,6 +27,16 @@ var Analyzer = &analysis.Analyzer{ const Doc = "check if there is any context parameter in the code, that is not the first argument to a function or that's not named 'ctx'" func run(pass *analysis.Pass) (interface{}, error) { + for _, file := range pass.Files { + for _, cg := range file.Comments { + for _, c := range cg.List { + if isIgnoreComment(c.Text) { + return nil, nil + } + } + } + } + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) inspect.Preorder([]ast.Node{ (*ast.FuncType)(nil), @@ -71,3 +82,7 @@ func checkFunction(fn *ast.FuncType, pass *analysis.Pass) { } } } + +func isIgnoreComment(comment string) bool { + return strings.HasPrefix(comment, "// Code generated by") +} diff --git a/internal/tool/generate/keywordtrie/main.go b/internal/tool/generate/keywordtrie/main.go index 97005ebd..873a020d 100644 --- a/internal/tool/generate/keywordtrie/main.go +++ b/internal/tool/generate/keywordtrie/main.go @@ -23,8 +23,7 @@ func scanKeyword{{ sanitize .path }}(s RuneScanner) (token.Type, bool) { {{ if .tokenType }}return {{ .tokenType }}, true{{ else }}return token.Unknown, false{{ end }} }{{ if .nextRunes }} switch next { {{- range .nextRunes }} - {{ $low := lower . }} - case '{{ . }}'{{ if eq . $low }}{{ else }}, '{{ $low }}'{{ end }}: + {{ $low := lower . }}case '{{ . }}'{{ if eq . $low }}{{ else }}, '{{ $low }}'{{ end }}: s.ConsumeRune() return scanKeyword{{ sanitize $.path }}{{ sanitize . }}(s){{ end }} }{{ end }} @@ -41,8 +40,8 @@ func defaultKeywordsRule(s RuneScanner) (token.Type, bool) { if !ok { return token.Unknown, false } - peek, noEof := s.Lookahead() - if noEof && defaultLiteral.Matches(peek) { // keywords must be terminated with a whitespace + peek, noEOF := s.Lookahead() + if noEOF && defaultLiteral.Matches(peek) { // keywords must be terminated with a whitespace return token.Unknown, false } return tok, ok