diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml index 401a147edb1..854393c25f9 100644 --- a/.github/workflows/cluster_endtoend.yml +++ b/.github/workflows/cluster_endtoend.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - name: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + name: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26] steps: - name: Set up Go diff --git a/Makefile b/Makefile index 3ac2812393c..96607e3c86c 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,8 @@ ifndef NOBANNER echo $$(date): Building source tree endif bash ./build.env - go install $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) -ldflags "$(shell tools/build_version_flags.sh)" ./go/... + go install $(EXTRA_BUILD_FLAGS) $(VT_GO_PARALLEL) -ldflags "$(shell tools/build_version_flags.sh)" ./go/... && \ + (cd go/cmd/vttablet && go run github.com/GeertJohan/go.rice/rice append --exec=../../../bin/vttablet) debug: ifndef NOBANNER diff --git a/docker/mini/vttablet-mini-up.sh b/docker/mini/vttablet-mini-up.sh index 0dbb73c5f87..065f428ddb5 100755 --- a/docker/mini/vttablet-mini-up.sh +++ b/docker/mini/vttablet-mini-up.sh @@ -50,8 +50,6 @@ vttablet \ -init_shard $shard \ -init_tablet_type $tablet_type \ -health_check_interval 5s \ - -heartbeat_enable \ - -heartbeat_interval 250ms \ -enable_semi_sync \ -enable_replication_reporter \ -backup_storage_implementation file \ diff --git a/examples/local/scripts/vttablet-up.sh b/examples/local/scripts/vttablet-up.sh index 71e47c59d59..c3f66fa806d 100755 --- a/examples/local/scripts/vttablet-up.sh +++ b/examples/local/scripts/vttablet-up.sh @@ -47,8 +47,6 @@ vttablet \ -health_check_interval 5s \ -enable_semi_sync \ -enable_replication_reporter \ - -heartbeat_enable \ - -heartbeat_interval 250ms \ -backup_storage_implementation file \ -file_backup_storage_root $VTDATAROOT/backups \ -restore_from_backup \ diff --git a/go.mod b/go.mod index 90086484433..3f20e4a8295 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,6 @@ require ( github.com/Azure/go-autorest/autorest v0.10.0 // indirect github.com/GeertJohan/go.rice v1.0.0 github.com/PuerkitoBio/goquery v1.5.1 - github.com/TylerBrock/colorjson v0.0.0-20180527164720-95ec53f28296 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 github.com/aws/aws-sdk-go v1.28.8 @@ -25,13 +24,14 @@ require ( github.com/evanphx/json-patch v4.5.0+incompatible github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab github.com/go-sql-driver/mysql v1.5.0 - github.com/gogo/protobuf v1.3.1 + github.com/gogo/protobuf v1.3.1 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/mock v1.3.1 github.com/golang/protobuf v1.3.2 github.com/golang/snappy v0.0.1 github.com/google/go-cmp v0.4.0 + github.com/google/uuid v1.1.1 github.com/googleapis/gnostic v0.2.0 // indirect github.com/gorilla/websocket v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware v1.1.0 @@ -52,13 +52,11 @@ require ( github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/krishicks/yaml-patch v0.0.10 github.com/magiconair/properties v1.8.1 - github.com/manifoldco/promptui v0.7.0 github.com/martini-contrib/auth v0.0.0-20150219114609-fa62c19b7ae8 github.com/martini-contrib/gzip v0.0.0-20151124214156-6c035326b43f github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 github.com/mattn/go-sqlite3 v1.14.0 github.com/minio/minio-go v0.0.0-20190131015406-c8a261de75c1 - github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/go-testing-interface v1.14.0 // indirect github.com/mitchellh/mapstructure v1.2.3 // indirect github.com/montanaflynn/stats v0.6.3 @@ -80,7 +78,6 @@ require ( github.com/satori/go.uuid v1.2.0 // indirect github.com/sjmudd/stopwatch v0.0.0-20170613150411-f380bf8a9be1 github.com/smartystreets/goconvey v1.6.4 // indirect - github.com/spf13/cobra v0.0.5 github.com/stretchr/testify v1.4.0 github.com/tchap/go-patricia v0.0.0-20160729071656-dd168db6051b github.com/tebeka/selenium v0.9.9 diff --git a/go.sum b/go.sum index 10e55d0e67b..017ce039aa5 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,6 @@ github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/TylerBrock/colorjson v0.0.0-20180527164720-95ec53f28296 h1:JYWTroLXcNzSCgu66NMgdjwoMHQRbv2SoOVNFb4kRkE= -github.com/TylerBrock/colorjson v0.0.0-20180527164720-95ec53f28296/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/akavel/rsrc v0.8.0 h1:zjWn7ukO9Kc5Q62DOJCcxGpXC18RawVtYAGdz2aLlfw= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= @@ -98,10 +96,6 @@ github.com/buger/jsonparser v0.0.0-20200322175846-f7e751efca13 h1:+qUNY4VRkEH46b github.com/buger/jsonparser v0.0.0-20200322175846-f7e751efca13/go.mod h1:tgcrVJ81GPSF0mz+0nu1Xaz0fazGPrmmJfJtxjbHhUQ= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA= @@ -369,8 +363,6 @@ github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpR github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= @@ -397,8 +389,6 @@ 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/krishicks/yaml-patch v0.0.10 h1:H4FcHpnNwVmw8u0MjPRjWyIXtco6zM2F78t+57oNM3E= github.com/krishicks/yaml-patch v0.0.10/go.mod h1:Sm5TchwZS6sm7RJoyg87tzxm2ZcKzdRE4Q7TjNhPrME= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -409,8 +399,6 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4= -github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/martini-contrib/auth v0.0.0-20150219114609-fa62c19b7ae8 h1:1ded5x5QpCLsyTH5ct62Rh1RXPFnn0/dubCqAeh+stU= github.com/martini-contrib/auth v0.0.0-20150219114609-fa62c19b7ae8/go.mod h1:ahTFgV/NtzY/CALneRrC67m1dis5arHTQDfyIhKk69E= github.com/martini-contrib/gzip v0.0.0-20151124214156-6c035326b43f h1:wVDxEVZP1eiPIlHVaafUAEUDtyl6ytjHv3egJVbyfOk= @@ -434,7 +422,6 @@ github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHX github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA= @@ -452,8 +439,6 @@ github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= 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/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= -github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= @@ -481,8 +466,6 @@ github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5 h1:58+kh9C6jJVXYjt8IE48G2eWl6BjwU5Gj0gqY84fy78= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5-0.20200416053754-163badb3bac6 h1:F721VBMijn0OBFZ5wUSuMVVLQj2IJiiupn6UNd7UbBE= github.com/olekukonko/tablewriter v0.0.5-0.20200416053754-163badb3bac6/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -503,7 +486,6 @@ github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwU github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/patrickmn/go-cache v1.0.0 h1:3gD5McaYs9CxjyK5AXGcq8gdeCARtd/9gJDUvVeaZ0Y= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= @@ -717,6 +699,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjut golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -725,7 +708,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= 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= @@ -737,7 +719,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -758,10 +739,8 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -800,7 +779,6 @@ golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191219041853-979b82bfef62 h1:vDaiisQl0rGVXqk3wT2yc43gSnwlj4haEG5J78IGZP4= golang.org/x/tools v0.0.0-20191219041853-979b82bfef62/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= 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= @@ -808,7 +786,6 @@ gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0 h1:9sdfJOzWlkqPltHAuzT2Cp+yrBeY1KRVYgms8soxMwM= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8= @@ -824,15 +801,12 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190626174449-989357319d63/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64 h1:iKtrH9Y8mcbADOP0YFaEMth7OfuHY9xHOwNj4znpM1A= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195 h1:dWzgMaXfaHsnkRKZ1l3iJLDmTEB40JMl/dqRbJX4D/o= google.golang.org/genproto v0.0.0-20190926190326-7ee9db18f195/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1 h1:j6XxA85m/6txkUCHvzlV5f+HBNl/1r5cZ2A/3IEFOO8= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0 h1:vb/1TCsVn3DcJlQ0Gs1yB1pKI6Do2/QNwxdKqmc/b0s= @@ -855,14 +829,12 @@ gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.41.0 h1:Ka3ViY6gNYSKiVy71zXBEqKplnV35ImDLVG+8uoIklE= gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ldap.v2 v2.5.0 h1:1rO3ojzsHUk+gq4ZYhC4Pg+EzWaaKIV8+DJwExS5/QQ= gopkg.in/ldap.v2 v2.5.0/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -871,9 +843,7 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= @@ -882,9 +852,7 @@ 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-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a h1:LJwr7TCTghdatWv40WobzlKXc9c4s8oGa7QKJUtHhWA= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/go/cmd/vttablet/vttablet.go b/go/cmd/vttablet/vttablet.go index 8fea9def342..50d857070ce 100644 --- a/go/cmd/vttablet/vttablet.go +++ b/go/cmd/vttablet/vttablet.go @@ -32,11 +32,14 @@ import ( "vitess.io/vitess/go/vt/tableacl/simpleacl" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vttablet/onlineddl" "vitess.io/vitess/go/vt/vttablet/tabletmanager" "vitess.io/vitess/go/vt/vttablet/tabletmanager/vreplication" "vitess.io/vitess/go/vt/vttablet/tabletserver" "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" "vitess.io/vitess/go/yaml2" + + rice "github.com/GeertJohan/go.rice" ) var ( @@ -77,6 +80,10 @@ func main() { mysqld := mysqlctl.NewMysqld(config.DB) servenv.OnClose(mysqld.Close) + if err := extractOnlineDDL(); err != nil { + log.Exitf("failed to extract online DDL binaries: %v", err) + } + // Initialize and start tm. gRPCPort := int32(0) if servenv.GRPCPort != nil { @@ -157,6 +164,27 @@ func initConfig(tabletAlias *topodatapb.TabletAlias) (*tabletenv.TabletConfig, * return config, mycnf } +// extractOnlineDDL extracts the gh-ost binary from this executable. gh-ost is appended +// to vttablet executable by `make build` and via ricebox +func extractOnlineDDL() error { + riceBox, err := rice.FindBox("../../../resources/bin") + if err != nil { + return err + } + + if binaryFileName, isOverride := onlineddl.GhostBinaryFileName(); !isOverride { + ghostBinary, err := riceBox.Bytes("gh-ost") + if err != nil { + return err + } + if err := ioutil.WriteFile(binaryFileName, ghostBinary, 0755); err != nil { + return err + } + } + + return nil +} + func createTabletServer(config *tabletenv.TabletConfig, ts *topo.Server, tabletAlias *topodatapb.TabletAlias) *tabletserver.TabletServer { if *tableACLConfig != "" { // To override default simpleacl, other ACL plugins must set themselves to be default ACL factory diff --git a/go/test/endtoend/cluster/vtctlclient_process.go b/go/test/endtoend/cluster/vtctlclient_process.go index 8be59625903..69f3e5d7f7f 100644 --- a/go/test/endtoend/cluster/vtctlclient_process.go +++ b/go/test/endtoend/cluster/vtctlclient_process.go @@ -47,14 +47,20 @@ func (vtctlclient *VtctlClientProcess) InitShardMaster(Keyspace string, Shard st return err } -// ApplySchema applies SQL schema to the keyspace -func (vtctlclient *VtctlClientProcess) ApplySchema(Keyspace string, SQL string) (err error) { - return vtctlclient.ExecuteCommand( +// ApplySchemaWithOutput applies SQL schema to the keyspace +func (vtctlclient *VtctlClientProcess) ApplySchemaWithOutput(Keyspace string, SQL string) (result string, err error) { + return vtctlclient.ExecuteCommandWithOutput( "ApplySchema", "-sql", SQL, Keyspace) } +// ApplySchema applies SQL schema to the keyspace +func (vtctlclient *VtctlClientProcess) ApplySchema(Keyspace string, SQL string) (err error) { + _, err = vtctlclient.ApplySchemaWithOutput(Keyspace, SQL) + return err +} + // ApplyVSchema applies vitess schema (JSON format) to the keyspace func (vtctlclient *VtctlClientProcess) ApplyVSchema(Keyspace string, JSON string) (err error) { return vtctlclient.ExecuteCommand( @@ -64,6 +70,36 @@ func (vtctlclient *VtctlClientProcess) ApplyVSchema(Keyspace string, JSON string ) } +// OnlineDDLShowRecent responds with recent schema migration list +func (vtctlclient *VtctlClientProcess) OnlineDDLShowRecent(Keyspace string) (result string, err error) { + return vtctlclient.ExecuteCommandWithOutput( + "OnlineDDL", + Keyspace, + "show", + "recent", + ) +} + +// OnlineDDLCancelMigration cancels a given migration uuid +func (vtctlclient *VtctlClientProcess) OnlineDDLCancelMigration(Keyspace, uuid string) (result string, err error) { + return vtctlclient.ExecuteCommandWithOutput( + "OnlineDDL", + Keyspace, + "cancel", + uuid, + ) +} + +// OnlineDDLRetryMigration retries a given migration uuid +func (vtctlclient *VtctlClientProcess) OnlineDDLRetryMigration(Keyspace, uuid string) (result string, err error) { + return vtctlclient.ExecuteCommandWithOutput( + "OnlineDDL", + Keyspace, + "retry", + uuid, + ) +} + // ExecuteCommand executes any vtctlclient command func (vtctlclient *VtctlClientProcess) ExecuteCommand(args ...string) (err error) { output, err := vtctlclient.ExecuteCommandWithOutput(args...) diff --git a/go/test/endtoend/cluster/vtctld_process.go b/go/test/endtoend/cluster/vtctld_process.go index 89bd7544496..64a5e2bed52 100644 --- a/go/test/endtoend/cluster/vtctld_process.go +++ b/go/test/endtoend/cluster/vtctld_process.go @@ -67,6 +67,8 @@ func (vtctld *VtctldProcess) Setup(cell string, extraArgs ...string) (err error) // hard-code these two soon-to-be deprecated drain values. "-wait_for_drain_sleep_rdonly", "1s", "-wait_for_drain_sleep_replica", "1s", + // short online-ddl check interval to hasten tests + "-online_ddl_check_interval", "2s", "-log_dir", vtctld.LogDir, "-port", fmt.Sprintf("%d", vtctld.Port), "-grpc_port", fmt.Sprintf("%d", vtctld.GrpcPort), diff --git a/go/test/endtoend/onlineddl/onlineddl_test.go b/go/test/endtoend/onlineddl/onlineddl_test.go new file mode 100644 index 00000000000..41f63843ef3 --- /dev/null +++ b/go/test/endtoend/onlineddl/onlineddl_test.go @@ -0,0 +1,259 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package onlineddl + +import ( + "flag" + "fmt" + "os" + "path" + "regexp" + "strings" + "testing" + "time" + + "vitess.io/vitess/go/vt/schema" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + hostname = "localhost" + keyspaceName = "ks" + cell = "zone1" + schemaChangeDirectory = "" + totalTableCount = 4 + createTable = ` + CREATE TABLE %s ( + id BIGINT(20) not NULL, + msg varchar(64), + PRIMARY KEY (id) + ) ENGINE=InnoDB;` + // The following statement is valid + alterTableSuccessfulStatament = ` + ALTER WITH 'gh-ost' TABLE %s + MODIFY id BIGINT UNSIGNED NOT NULL, + ADD COLUMN ghost_col INT NOT NULL, + ADD INDEX idx_msg(msg)` + // The following statement will fail because gh-ost requires some shared unique key + alterTableFailedStatament = ` + ALTER WITH 'gh-ost' TABLE %s + DROP PRIMARY KEY, + DROP COLUMN ghost_col` + alterTableThrottlingStatament = ` + ALTER WITH 'gh-ost' '--max-load=Threads_running=1' TABLE %s + DROP COLUMN ghost_col` +) + +func fullWordUUIDRegexp(uuid, searchWord string) *regexp.Regexp { + return regexp.MustCompile(uuid + `.*?\b` + searchWord + `\b`) +} +func fullWordRegexp(searchWord string) *regexp.Regexp { + return regexp.MustCompile(`.*?\b` + searchWord + `\b`) +} + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitcode, err := func() (int, error) { + clusterInstance = cluster.NewCluster(cell, hostname) + schemaChangeDirectory = path.Join("/tmp", fmt.Sprintf("schema_change_dir_%d", clusterInstance.GetAndReserveTabletUID())) + defer os.RemoveAll(schemaChangeDirectory) + defer clusterInstance.Teardown() + + if _, err := os.Stat(schemaChangeDirectory); os.IsNotExist(err) { + _ = os.Mkdir(schemaChangeDirectory, 0700) + } + + clusterInstance.VtctldExtraArgs = []string{ + "-schema_change_dir", schemaChangeDirectory, + "-schema_change_controller", "local", + "-schema_change_check_interval", "1"} + + clusterInstance.VtTabletExtraArgs = []string{ + "-migration_check_interval", "5s", + } + + if err := clusterInstance.StartTopo(); err != nil { + return 1, err + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + } + + if err := clusterInstance.StartUnshardedKeyspace(*keyspace, 2, true); err != nil { + return 1, err + } + if err := clusterInstance.StartKeyspace(*keyspace, []string{"1"}, 1, false); err != nil { + return 1, err + } + return m.Run(), nil + }() + if err != nil { + fmt.Printf("%v\n", err) + os.Exit(1) + } else { + os.Exit(exitcode) + } + +} + +func TestSchemaChange(t *testing.T) { + defer cluster.PanicHandler(t) + assert.Equal(t, 2, len(clusterInstance.Keyspaces[0].Shards)) + testWithInitialSchema(t) + { + uuid := testAlterTable(t, alterTableSuccessfulStatament) + checkRecentMigrations(t, uuid, schema.OnlineDDLStatusComplete) + checkCancelMigration(t, uuid, false) + checkRetryMigration(t, uuid, false) + } + { + uuid := testAlterTable(t, alterTableThrottlingStatament) + checkRecentMigrations(t, uuid, schema.OnlineDDLStatusRunning) + checkCancelMigration(t, uuid, true) + time.Sleep(2 * time.Second) + checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) + } + { + uuid := testAlterTable(t, alterTableFailedStatament) + checkRecentMigrations(t, uuid, schema.OnlineDDLStatusFailed) + checkCancelMigration(t, uuid, false) + checkRetryMigration(t, uuid, true) + } +} + +func testWithInitialSchema(t *testing.T) { + // Create 4 tables + var sqlQuery = "" //nolint + for i := 0; i < totalTableCount; i++ { + sqlQuery = fmt.Sprintf(createTable, fmt.Sprintf("vt_onlineddl_test_%02d", i)) + err := clusterInstance.VtctlclientProcess.ApplySchema(keyspaceName, sqlQuery) + require.Nil(t, err) + } + + // Check if 4 tables are created + checkTables(t, totalTableCount) +} + +// testAlterTable runs an online DDL, ALTER statement +func testAlterTable(t *testing.T, alterStatement string) (uuid string) { + tableName := fmt.Sprintf("vt_onlineddl_test_%02d", 3) + sqlQuery := fmt.Sprintf(alterStatement, tableName) + uuid, err := clusterInstance.VtctlclientProcess.ApplySchemaWithOutput(keyspaceName, sqlQuery) + require.Nil(t, err) + uuid = strings.TrimSpace(uuid) + require.NotEmpty(t, uuid) + // Migration is asynchronous. Give it some time. + time.Sleep(time.Second * 20) + checkMigratedTable(t, tableName) + return uuid +} + +// checkTables checks the number of tables in the first two shards. +func checkTables(t *testing.T, count int) { + for i := range clusterInstance.Keyspaces[0].Shards { + checkTablesCount(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], count) + } +} + +// checkTablesCount checks the number of tables in the given tablet +func checkTablesCount(t *testing.T, tablet *cluster.Vttablet, count int) { + queryResult, err := tablet.VttabletProcess.QueryTablet("show tables;", keyspaceName, true) + require.Nil(t, err) + assert.Equal(t, len(queryResult.Rows), count) +} + +// checkRecentMigrations checks 'OnlineDDL show recent' output. Example to such output: +// +------------------+-------+--------------+----------------------+--------------------------------------+----------+---------------------+---------------------+------------------+ +// | Tablet | shard | mysql_schema | mysql_table | migration_uuid | strategy | started_timestamp | completed_timestamp | migration_status | +// +------------------+-------+--------------+----------------------+--------------------------------------+----------+---------------------+---------------------+------------------+ +// | zone1-0000003880 | 0 | vt_ks | vt_onlineddl_test_03 | a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9a | gh-ost | 2020-09-01 17:50:40 | 2020-09-01 17:50:41 | complete | +// | zone1-0000003884 | 1 | vt_ks | vt_onlineddl_test_03 | a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9a | gh-ost | 2020-09-01 17:50:40 | 2020-09-01 17:50:41 | complete | +// +------------------+-------+--------------+----------------------+--------------------------------------+----------+---------------------+---------------------+------------------+ + +func checkRecentMigrations(t *testing.T, uuid string, expectStatus schema.OnlineDDLStatus) { + result, err := clusterInstance.VtctlclientProcess.OnlineDDLShowRecent(keyspaceName) + assert.NoError(t, err) + fmt.Println("# 'vtctlclient OnlineDDL show recent' output (for debug purposes):") + fmt.Println(result) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), strings.Count(result, uuid)) + // We ensure "full word" regexp becuase some column names may conflict + expectStatusRegexp := fullWordUUIDRegexp(uuid, string(expectStatus)) + m := expectStatusRegexp.FindAllString(result, -1) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), len(m)) +} + +// checkCancelMigration attempts to cancel a migration, and expects rejection +func checkCancelMigration(t *testing.T, uuid string, expectCancelPossible bool) { + result, err := clusterInstance.VtctlclientProcess.OnlineDDLCancelMigration(keyspaceName, uuid) + fmt.Println("# 'vtctlclient OnlineDDL cancel ' output (for debug purposes):") + fmt.Println(result) + assert.NoError(t, err) + + var r *regexp.Regexp + if expectCancelPossible { + r = fullWordRegexp("1") + } else { + r = fullWordRegexp("0") + } + m := r.FindAllString(result, -1) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), len(m)) +} + +// checkRetryMigration attempts to retry a migration, and expects rejection +func checkRetryMigration(t *testing.T, uuid string, expectRetryPossible bool) { + result, err := clusterInstance.VtctlclientProcess.OnlineDDLRetryMigration(keyspaceName, uuid) + fmt.Println("# 'vtctlclient OnlineDDL retry ' output (for debug purposes):") + fmt.Println(result) + assert.NoError(t, err) + + var r *regexp.Regexp + if expectRetryPossible { + r = fullWordRegexp("1") + } else { + r = fullWordRegexp("0") + } + m := r.FindAllString(result, -1) + assert.Equal(t, len(clusterInstance.Keyspaces[0].Shards), len(m)) +} + +// checkMigratedTables checks the CREATE STATEMENT of a table after migration +func checkMigratedTable(t *testing.T, tableName string) { + expect := "ghost_col" + for i := range clusterInstance.Keyspaces[0].Shards { + createStatement := getCreateTableStatement(t, clusterInstance.Keyspaces[0].Shards[i].Vttablets[0], tableName) + assert.Contains(t, createStatement, expect) + } +} + +// getCreateTableStatement returns the CREATE TABLE statement for a given table +func getCreateTableStatement(t *testing.T, tablet *cluster.Vttablet, tableName string) (statement string) { + queryResult, err := tablet.VttabletProcess.QueryTablet(fmt.Sprintf("show create table %s;", tableName), keyspaceName, true) + require.Nil(t, err) + + assert.Equal(t, len(queryResult.Rows), 1) + assert.Equal(t, len(queryResult.Rows[0]), 2) // table name, create statement + statement = queryResult.Rows[0][1].ToString() + return statement +} diff --git a/go/test/endtoend/tabletmanager/throttler/throttler_test.go b/go/test/endtoend/tabletmanager/throttler/throttler_test.go index 02f2ad58675..cc4cfb7612d 100644 --- a/go/test/endtoend/tabletmanager/throttler/throttler_test.go +++ b/go/test/endtoend/tabletmanager/throttler/throttler_test.go @@ -88,6 +88,7 @@ func TestMain(m *testing.M) { "-lock_tables_timeout", "5s", "-watch_replication_stream", "-enable_replication_reporter", + "-enable-lag-throttler", "-heartbeat_enable", "-heartbeat_interval", "250ms", } diff --git a/go/textutil/hash.go b/go/textutil/hash.go new file mode 100644 index 00000000000..4fc70fdb072 --- /dev/null +++ b/go/textutil/hash.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package textutil + +import ( + "crypto/rand" + "crypto/sha256" + "encoding/hex" +) + +// RandomHash returns a 64 hex character random string +func RandomHash() string { + size := 64 + rb := make([]byte, size) + _, _ = rand.Read(rb) + + hasher := sha256.New() + hasher.Write(rb) + return hex.EncodeToString(hasher.Sum(nil)) +} diff --git a/go/textutil/strings.go b/go/textutil/strings.go new file mode 100644 index 00000000000..e7cdce3dbdb --- /dev/null +++ b/go/textutil/strings.go @@ -0,0 +1,39 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package textutil + +import ( + "regexp" + "strings" +) + +var ( + delimitedListRegexp = regexp.MustCompile(`[ ,;]+`) +) + +// SplitDelimitedList splits a given string by comma, semi-colon or space, and returns non-empty strings +func SplitDelimitedList(s string) (list []string) { + tokens := delimitedListRegexp.Split(s, -1) + for _, token := range tokens { + token = strings.TrimSpace(token) + if token == "" { + continue + } + list = append(list, token) + } + return list +} diff --git a/go/textutil/strings_test.go b/go/textutil/strings_test.go new file mode 100644 index 00000000000..b8a6eef403b --- /dev/null +++ b/go/textutil/strings_test.go @@ -0,0 +1,46 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package textutil + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSplitDelimitedList(t *testing.T) { + defaultList := []string{"one", "two", "three"} + tt := []struct { + s string + list []string + }{ + {s: "one,two,three"}, + {s: "one, two, three"}, + {s: "one,two; three "}, + {s: "one two three"}, + {s: "one,,,two,three"}, + {s: " one, ,two, three "}, + } + + for _, tc := range tt { + if tc.list == nil { + tc.list = defaultList + } + list := SplitDelimitedList(tc.s) + assert.Equal(t, tc.list, list) + } +} diff --git a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go index c5290d4b947..e6f519587a3 100644 --- a/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go +++ b/go/vt/proto/tabletmanagerdata/tabletmanagerdata.pb.go @@ -4375,6 +4375,100 @@ func (m *SlaveWasRestartedResponse) XXX_DiscardUnknown() { var xxx_messageInfo_SlaveWasRestartedResponse proto.InternalMessageInfo +type VExecRequest struct { + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + Workflow string `protobuf:"bytes,2,opt,name=workflow,proto3" json:"workflow,omitempty"` + Keyspace string `protobuf:"bytes,3,opt,name=keyspace,proto3" json:"keyspace,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VExecRequest) Reset() { *m = VExecRequest{} } +func (m *VExecRequest) String() string { return proto.CompactTextString(m) } +func (*VExecRequest) ProtoMessage() {} +func (*VExecRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ff9ac4f89e61ffa4, []int{110} +} + +func (m *VExecRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VExecRequest.Unmarshal(m, b) +} +func (m *VExecRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VExecRequest.Marshal(b, m, deterministic) +} +func (m *VExecRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_VExecRequest.Merge(m, src) +} +func (m *VExecRequest) XXX_Size() int { + return xxx_messageInfo_VExecRequest.Size(m) +} +func (m *VExecRequest) XXX_DiscardUnknown() { + xxx_messageInfo_VExecRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_VExecRequest proto.InternalMessageInfo + +func (m *VExecRequest) GetQuery() string { + if m != nil { + return m.Query + } + return "" +} + +func (m *VExecRequest) GetWorkflow() string { + if m != nil { + return m.Workflow + } + return "" +} + +func (m *VExecRequest) GetKeyspace() string { + if m != nil { + return m.Keyspace + } + return "" +} + +type VExecResponse struct { + Result *query.QueryResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *VExecResponse) Reset() { *m = VExecResponse{} } +func (m *VExecResponse) String() string { return proto.CompactTextString(m) } +func (*VExecResponse) ProtoMessage() {} +func (*VExecResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ff9ac4f89e61ffa4, []int{111} +} + +func (m *VExecResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_VExecResponse.Unmarshal(m, b) +} +func (m *VExecResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_VExecResponse.Marshal(b, m, deterministic) +} +func (m *VExecResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_VExecResponse.Merge(m, src) +} +func (m *VExecResponse) XXX_Size() int { + return xxx_messageInfo_VExecResponse.Size(m) +} +func (m *VExecResponse) XXX_DiscardUnknown() { + xxx_messageInfo_VExecResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_VExecResponse proto.InternalMessageInfo + +func (m *VExecResponse) GetResult() *query.QueryResult { + if m != nil { + return m.Result + } + return nil +} + func init() { proto.RegisterType((*TableDefinition)(nil), "tabletmanagerdata.TableDefinition") proto.RegisterType((*SchemaDefinition)(nil), "tabletmanagerdata.SchemaDefinition") @@ -4489,153 +4583,157 @@ func init() { proto.RegisterType((*SlaveWasPromotedResponse)(nil), "tabletmanagerdata.SlaveWasPromotedResponse") proto.RegisterType((*SlaveWasRestartedRequest)(nil), "tabletmanagerdata.SlaveWasRestartedRequest") proto.RegisterType((*SlaveWasRestartedResponse)(nil), "tabletmanagerdata.SlaveWasRestartedResponse") + proto.RegisterType((*VExecRequest)(nil), "tabletmanagerdata.VExecRequest") + proto.RegisterType((*VExecResponse)(nil), "tabletmanagerdata.VExecResponse") } func init() { proto.RegisterFile("tabletmanagerdata.proto", fileDescriptor_ff9ac4f89e61ffa4) } var fileDescriptor_ff9ac4f89e61ffa4 = []byte{ - // 2276 bytes of a gzipped FileDescriptorProto + // 2316 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0xdd, 0x72, 0xdb, 0xc6, - 0x15, 0x1e, 0x50, 0x3f, 0x96, 0x0e, 0x7f, 0x44, 0x81, 0x94, 0x44, 0x51, 0xb1, 0x2c, 0xc3, 0x4e, - 0xe2, 0x26, 0x53, 0x2a, 0x51, 0x12, 0x4f, 0x26, 0xfd, 0x99, 0xca, 0xb6, 0x64, 0x3b, 0x96, 0x63, - 0x05, 0xb2, 0xe3, 0x4c, 0xa6, 0x53, 0x0c, 0x48, 0xac, 0x28, 0x8c, 0x40, 0x2c, 0xbc, 0xbb, 0xa0, - 0xc4, 0x9b, 0x3e, 0x42, 0xfb, 0x02, 0x9d, 0xde, 0x74, 0xa6, 0xbd, 0xef, 0x43, 0xf4, 0x11, 0xd2, - 0x47, 0xe9, 0x45, 0x2f, 0xda, 0xd9, 0xdd, 0x03, 0x12, 0x20, 0x20, 0x59, 0x76, 0xdd, 0x99, 0xdc, - 0x68, 0xb0, 0xdf, 0xd9, 0xf3, 0xbb, 0x67, 0xcf, 0x39, 0x4b, 0xc1, 0x9a, 0x70, 0xbb, 0x01, 0x11, - 0x03, 0x37, 0x74, 0xfb, 0x84, 0x79, 0xae, 0x70, 0x3b, 0x11, 0xa3, 0x82, 0x9a, 0xcb, 0x39, 0x42, - 0xbb, 0xfc, 0x2a, 0x26, 0x6c, 0xa4, 0xe9, 0xed, 0x9a, 0xa0, 0x11, 0x9d, 0xec, 0x6f, 0xaf, 0x30, - 0x12, 0x05, 0x7e, 0xcf, 0x15, 0x3e, 0x0d, 0x53, 0x70, 0x35, 0xa0, 0xfd, 0x58, 0xf8, 0x81, 0x5e, - 0x5a, 0xff, 0x31, 0x60, 0xe9, 0xb9, 0x14, 0xfc, 0x80, 0x1c, 0xfb, 0xa1, 0x2f, 0x37, 0x9b, 0x26, - 0xcc, 0x86, 0xee, 0x80, 0xb4, 0x8c, 0x2d, 0xe3, 0xce, 0xa2, 0xad, 0xbe, 0xcd, 0x55, 0x98, 0xe7, - 0xbd, 0x13, 0x32, 0x70, 0x5b, 0x25, 0x85, 0xe2, 0xca, 0x6c, 0xc1, 0xb5, 0x1e, 0x0d, 0xe2, 0x41, - 0xc8, 0x5b, 0x33, 0x5b, 0x33, 0x77, 0x16, 0xed, 0x64, 0x69, 0x76, 0xa0, 0x11, 0x31, 0x7f, 0xe0, - 0xb2, 0x91, 0x73, 0x4a, 0x46, 0x4e, 0xb2, 0x6b, 0x56, 0xed, 0x5a, 0x46, 0xd2, 0x13, 0x32, 0xba, - 0x8f, 0xfb, 0x4d, 0x98, 0x15, 0xa3, 0x88, 0xb4, 0xe6, 0xb4, 0x56, 0xf9, 0x6d, 0xde, 0x80, 0xb2, - 0x34, 0xdd, 0x09, 0x48, 0xd8, 0x17, 0x27, 0xad, 0xf9, 0x2d, 0xe3, 0xce, 0xac, 0x0d, 0x12, 0x3a, - 0x50, 0x88, 0xb9, 0x01, 0x8b, 0x8c, 0x9e, 0x39, 0x3d, 0x1a, 0x87, 0xa2, 0x75, 0x4d, 0x91, 0x17, - 0x18, 0x3d, 0xbb, 0x2f, 0xd7, 0xe6, 0x6d, 0x98, 0x3f, 0xf6, 0x49, 0xe0, 0xf1, 0xd6, 0xc2, 0xd6, - 0xcc, 0x9d, 0xf2, 0x4e, 0xa5, 0xa3, 0xe3, 0xb5, 0x2f, 0x41, 0x1b, 0x69, 0xd6, 0x5f, 0x0d, 0xa8, - 0x1f, 0x29, 0x67, 0x52, 0x21, 0xf8, 0x10, 0x96, 0xa4, 0x96, 0xae, 0xcb, 0x89, 0x83, 0x7e, 0xeb, - 0x68, 0xd4, 0x12, 0x58, 0xb3, 0x98, 0xcf, 0x40, 0x9f, 0x8b, 0xe3, 0x8d, 0x99, 0x79, 0xab, 0xa4, - 0xd4, 0x59, 0x9d, 0xfc, 0x51, 0x4e, 0x85, 0xda, 0xae, 0x8b, 0x2c, 0xc0, 0x65, 0x40, 0x87, 0x84, - 0x71, 0x9f, 0x86, 0xad, 0x19, 0xa5, 0x31, 0x59, 0x4a, 0x43, 0x4d, 0xad, 0xf5, 0xfe, 0x89, 0x1b, - 0xf6, 0x89, 0x4d, 0x78, 0x1c, 0x08, 0xf3, 0x11, 0x54, 0xbb, 0xe4, 0x98, 0xb2, 0x8c, 0xa1, 0xe5, - 0x9d, 0x5b, 0x05, 0xda, 0xa7, 0xdd, 0xb4, 0x2b, 0x9a, 0x13, 0x7d, 0xd9, 0x87, 0x8a, 0x7b, 0x2c, - 0x08, 0x73, 0x52, 0x27, 0x7d, 0x45, 0x41, 0x65, 0xc5, 0xa8, 0x61, 0xeb, 0x5f, 0x06, 0xd4, 0x5e, - 0x70, 0xc2, 0x0e, 0x09, 0x1b, 0xf8, 0x9c, 0x63, 0x4a, 0x9d, 0x50, 0x2e, 0x92, 0x94, 0x92, 0xdf, - 0x12, 0x8b, 0x39, 0x61, 0x98, 0x50, 0xea, 0xdb, 0xfc, 0x18, 0x96, 0x23, 0x97, 0xf3, 0x33, 0xca, - 0x3c, 0xa7, 0x77, 0x42, 0x7a, 0xa7, 0x3c, 0x1e, 0xa8, 0x38, 0xcc, 0xda, 0xf5, 0x84, 0x70, 0x1f, - 0x71, 0xf3, 0x5b, 0x80, 0x88, 0xf9, 0x43, 0x3f, 0x20, 0x7d, 0xa2, 0x13, 0xab, 0xbc, 0xf3, 0x69, - 0x81, 0xb5, 0x59, 0x5b, 0x3a, 0x87, 0x63, 0x9e, 0xbd, 0x50, 0xb0, 0x91, 0x9d, 0x12, 0xd2, 0xfe, - 0x15, 0x2c, 0x4d, 0x91, 0xcd, 0x3a, 0xcc, 0x9c, 0x92, 0x11, 0x5a, 0x2e, 0x3f, 0xcd, 0x26, 0xcc, - 0x0d, 0xdd, 0x20, 0x26, 0x68, 0xb9, 0x5e, 0x7c, 0x55, 0xfa, 0xd2, 0xb0, 0x7e, 0x34, 0xa0, 0xf2, - 0xa0, 0xfb, 0x1a, 0xbf, 0x6b, 0x50, 0xf2, 0xba, 0xc8, 0x5b, 0xf2, 0xba, 0xe3, 0x38, 0xcc, 0xa4, - 0xe2, 0xf0, 0xac, 0xc0, 0xb5, 0xed, 0x02, 0xd7, 0xd2, 0xca, 0xfe, 0x9f, 0x8e, 0xfd, 0xc5, 0x80, - 0xf2, 0x44, 0x13, 0x37, 0x0f, 0xa0, 0x2e, 0xed, 0x74, 0xa2, 0x09, 0xd6, 0x32, 0x94, 0x95, 0x37, - 0x5f, 0x7b, 0x00, 0xf6, 0x52, 0x9c, 0x59, 0x73, 0x73, 0x1f, 0x6a, 0x5e, 0x37, 0x23, 0x4b, 0xdf, - 0xa0, 0x1b, 0xaf, 0xf1, 0xd8, 0xae, 0x7a, 0xa9, 0x15, 0xb7, 0x3e, 0x84, 0xf2, 0xa1, 0x1f, 0xf6, - 0x6d, 0xf2, 0x2a, 0x26, 0x5c, 0xc8, 0xab, 0x14, 0xb9, 0xa3, 0x80, 0xba, 0x1e, 0x3a, 0x99, 0x2c, - 0xad, 0x3b, 0x50, 0xd1, 0x1b, 0x79, 0x44, 0x43, 0x4e, 0x2e, 0xd9, 0xf9, 0x11, 0x54, 0x8e, 0x02, - 0x42, 0xa2, 0x44, 0x66, 0x1b, 0x16, 0xbc, 0x98, 0xa9, 0xa2, 0xaa, 0xb6, 0xce, 0xd8, 0xe3, 0xb5, - 0xb5, 0x04, 0x55, 0xdc, 0xab, 0xc5, 0x5a, 0xff, 0x34, 0xc0, 0xdc, 0x3b, 0x27, 0xbd, 0x58, 0x90, - 0x47, 0x94, 0x9e, 0x26, 0x32, 0x8a, 0xea, 0xeb, 0x26, 0x40, 0xe4, 0x32, 0x77, 0x40, 0x04, 0x61, - 0xda, 0xfd, 0x45, 0x3b, 0x85, 0x98, 0x87, 0xb0, 0x48, 0xce, 0x05, 0x73, 0x1d, 0x12, 0x0e, 0x55, - 0xa5, 0x2d, 0xef, 0x7c, 0x56, 0x10, 0x9d, 0xbc, 0xb6, 0xce, 0x9e, 0x64, 0xdb, 0x0b, 0x87, 0x3a, - 0x27, 0x16, 0x08, 0x2e, 0xdb, 0xbf, 0x80, 0x6a, 0x86, 0xf4, 0x46, 0xf9, 0x70, 0x0c, 0x8d, 0x8c, - 0x2a, 0x8c, 0xe3, 0x0d, 0x28, 0x93, 0x73, 0x5f, 0x38, 0x5c, 0xb8, 0x22, 0xe6, 0x18, 0x20, 0x90, - 0xd0, 0x91, 0x42, 0x54, 0x1b, 0x11, 0x1e, 0x8d, 0xc5, 0xb8, 0x8d, 0xa8, 0x15, 0xe2, 0x84, 0x25, - 0xb7, 0x00, 0x57, 0xd6, 0x10, 0xea, 0x0f, 0x89, 0xd0, 0x75, 0x25, 0x09, 0xdf, 0x2a, 0xcc, 0x2b, - 0xc7, 0x75, 0xc6, 0x2d, 0xda, 0xb8, 0x32, 0x6f, 0x41, 0xd5, 0x0f, 0x7b, 0x41, 0xec, 0x11, 0x67, - 0xe8, 0x93, 0x33, 0xae, 0x54, 0x2c, 0xd8, 0x15, 0x04, 0xbf, 0x93, 0x98, 0xf9, 0x3e, 0xd4, 0xc8, - 0xb9, 0xde, 0x84, 0x42, 0x74, 0xdb, 0xaa, 0x22, 0xaa, 0x0a, 0x34, 0xb7, 0x08, 0x2c, 0xa7, 0xf4, - 0xa2, 0x77, 0x87, 0xb0, 0xac, 0x2b, 0x63, 0xaa, 0xd8, 0xbf, 0x49, 0xb5, 0xad, 0xf3, 0x29, 0xc4, - 0x5a, 0x83, 0x95, 0x87, 0x44, 0xa4, 0x52, 0x18, 0x7d, 0xb4, 0x7e, 0x80, 0xd5, 0x69, 0x02, 0x1a, - 0xf1, 0x1b, 0x28, 0x67, 0x2f, 0x9d, 0x54, 0xbf, 0x59, 0xa0, 0x3e, 0xcd, 0x9c, 0x66, 0xb1, 0x9a, - 0x60, 0x1e, 0x11, 0x61, 0x13, 0xd7, 0x7b, 0x16, 0x06, 0xa3, 0x44, 0xe3, 0x0a, 0x34, 0x32, 0x28, - 0xa6, 0xf0, 0x04, 0x7e, 0xc9, 0x7c, 0x41, 0x92, 0xdd, 0xab, 0xd0, 0xcc, 0xc2, 0xb8, 0xfd, 0x6b, - 0x58, 0xd6, 0xcd, 0xe9, 0xf9, 0x28, 0x4a, 0x36, 0x9b, 0x5f, 0x40, 0x59, 0x9b, 0xe7, 0xa8, 0x06, - 0x2f, 0x4d, 0xae, 0xed, 0x34, 0x3b, 0xe3, 0x79, 0x45, 0xc5, 0x5c, 0x28, 0x0e, 0x10, 0xe3, 0x6f, - 0x69, 0x67, 0x5a, 0xd6, 0xc4, 0x20, 0x9b, 0x1c, 0x33, 0xc2, 0x4f, 0x64, 0x4a, 0xa5, 0x0d, 0xca, - 0xc2, 0xb8, 0x7d, 0x0d, 0x56, 0xec, 0x38, 0x7c, 0x44, 0xdc, 0x40, 0x9c, 0xa8, 0xc6, 0x91, 0x30, - 0xb4, 0x60, 0x75, 0x9a, 0x80, 0x2c, 0x9f, 0x43, 0xeb, 0x71, 0x3f, 0xa4, 0x8c, 0x68, 0xe2, 0x1e, - 0x63, 0x94, 0x65, 0x4a, 0x8a, 0x10, 0x84, 0x85, 0x93, 0x42, 0xa1, 0x96, 0xd6, 0x06, 0xac, 0x17, - 0x70, 0xa1, 0xc8, 0xaf, 0xa4, 0xd1, 0xb2, 0x9e, 0x64, 0x33, 0xf9, 0x16, 0x54, 0xcf, 0x5c, 0x5f, - 0x38, 0x11, 0xe5, 0x93, 0x64, 0x5a, 0xb4, 0x2b, 0x12, 0x3c, 0x44, 0x4c, 0x7b, 0x96, 0xe6, 0x45, - 0x99, 0x3b, 0xb0, 0x7a, 0xc8, 0xc8, 0x71, 0xe0, 0xf7, 0x4f, 0xa6, 0x2e, 0x88, 0x9c, 0xc9, 0x54, - 0xe0, 0x92, 0x1b, 0x92, 0x2c, 0xad, 0x3e, 0xac, 0xe5, 0x78, 0x30, 0xaf, 0x0e, 0xa0, 0xa6, 0x77, - 0x39, 0x4c, 0xcd, 0x15, 0x49, 0x3d, 0x7f, 0xff, 0xc2, 0xcc, 0x4e, 0x4f, 0x21, 0x76, 0xb5, 0x97, - 0x5a, 0x71, 0xeb, 0xdf, 0x06, 0x98, 0xbb, 0x51, 0x14, 0x8c, 0xb2, 0x96, 0xd5, 0x61, 0x86, 0xbf, - 0x0a, 0x92, 0x12, 0xc3, 0x5f, 0x05, 0xb2, 0xc4, 0x1c, 0x53, 0xd6, 0x23, 0x78, 0x59, 0xf5, 0x42, - 0x8e, 0x01, 0x6e, 0x10, 0xd0, 0x33, 0x27, 0x35, 0xc3, 0xaa, 0xca, 0xb0, 0x60, 0xd7, 0x15, 0xc1, - 0x9e, 0xe0, 0xf9, 0x01, 0x68, 0xf6, 0x5d, 0x0d, 0x40, 0x73, 0x6f, 0x39, 0x00, 0xfd, 0xcd, 0x80, - 0x46, 0xc6, 0x7b, 0x8c, 0xf1, 0x4f, 0x6f, 0x54, 0x6b, 0xc0, 0xf2, 0x01, 0xed, 0x9d, 0xea, 0xaa, - 0x97, 0x5c, 0x8d, 0x26, 0x98, 0x69, 0x70, 0x72, 0xf1, 0x5e, 0x84, 0x41, 0x6e, 0xf3, 0x2a, 0x34, - 0xb3, 0x30, 0x6e, 0xff, 0xbb, 0x01, 0x2d, 0x6c, 0x11, 0xfb, 0x44, 0xf4, 0x4e, 0x76, 0xf9, 0x83, - 0xee, 0x38, 0x0f, 0x9a, 0x30, 0xa7, 0x46, 0x71, 0x15, 0x80, 0x8a, 0xad, 0x17, 0xe6, 0x1a, 0x5c, - 0xf3, 0xba, 0x8e, 0x6a, 0x8d, 0xd8, 0x1d, 0xbc, 0xee, 0x37, 0xb2, 0x39, 0xae, 0xc3, 0xc2, 0xc0, - 0x3d, 0x77, 0x18, 0x3d, 0xe3, 0x38, 0x0c, 0x5e, 0x1b, 0xb8, 0xe7, 0x36, 0x3d, 0xe3, 0x6a, 0x50, - 0xf7, 0xb9, 0x9a, 0xc0, 0xbb, 0x7e, 0x18, 0xd0, 0x3e, 0x57, 0xc7, 0xbf, 0x60, 0xd7, 0x10, 0xbe, - 0xa7, 0x51, 0x79, 0xd7, 0x98, 0xba, 0x46, 0xe9, 0xc3, 0x5d, 0xb0, 0x2b, 0x2c, 0x75, 0xb7, 0xac, - 0x87, 0xb0, 0x5e, 0x60, 0x33, 0x9e, 0xde, 0x47, 0x30, 0xaf, 0xaf, 0x06, 0x1e, 0x9b, 0x89, 0xcf, - 0x89, 0x6f, 0xe5, 0x5f, 0xbc, 0x06, 0xb8, 0xc3, 0xfa, 0x83, 0x01, 0xd7, 0xb3, 0x92, 0x76, 0x83, - 0x40, 0x0e, 0x60, 0xfc, 0xdd, 0x87, 0x20, 0xe7, 0xd9, 0x6c, 0x81, 0x67, 0x07, 0xb0, 0x79, 0x91, - 0x3d, 0x6f, 0xe1, 0xde, 0x93, 0xe9, 0xb3, 0xdd, 0x8d, 0xa2, 0xcb, 0x1d, 0x4b, 0xdb, 0x5f, 0xca, - 0xd8, 0x9f, 0x0f, 0xba, 0x12, 0xf6, 0x16, 0x56, 0xb5, 0xa1, 0x95, 0xaa, 0x0b, 0x7a, 0xe2, 0x48, - 0xd2, 0xf4, 0x00, 0xd6, 0x0b, 0x68, 0xa8, 0x64, 0x5b, 0x4e, 0x1f, 0xe3, 0x89, 0xa5, 0xbc, 0xb3, - 0xd6, 0x99, 0x7e, 0x3b, 0x23, 0x03, 0x6e, 0x93, 0x77, 0xe1, 0xa9, 0xcb, 0xe5, 0x35, 0xca, 0x28, - 0x79, 0x0a, 0xcd, 0x2c, 0x8c, 0xf2, 0xbf, 0x98, 0x92, 0x7f, 0x3d, 0x27, 0x3f, 0xc3, 0x96, 0x68, - 0x59, 0x83, 0x15, 0x8d, 0x27, 0xbd, 0x20, 0xd1, 0xf3, 0x39, 0xac, 0x4e, 0x13, 0x50, 0x53, 0x1b, - 0x16, 0xa6, 0x9a, 0xc9, 0x78, 0x2d, 0xb9, 0x5e, 0xba, 0xbe, 0xd8, 0xa7, 0xd3, 0xf2, 0x2e, 0xe5, - 0x5a, 0x87, 0xb5, 0x1c, 0x17, 0x5e, 0xf1, 0x16, 0xac, 0x1e, 0x09, 0x1a, 0xa5, 0xe2, 0x9a, 0x18, - 0xb8, 0x0e, 0x6b, 0x39, 0x0a, 0x32, 0xfd, 0x0e, 0xae, 0x4f, 0x91, 0x9e, 0xfa, 0xa1, 0x3f, 0x88, - 0x07, 0x57, 0x30, 0xc6, 0xbc, 0x09, 0xaa, 0x37, 0x3a, 0xc2, 0x1f, 0x90, 0x64, 0x88, 0x9c, 0xb1, - 0xcb, 0x12, 0x7b, 0xae, 0x21, 0xeb, 0x97, 0xb0, 0x79, 0x91, 0xfc, 0x2b, 0xc4, 0x48, 0x19, 0xee, - 0x32, 0x51, 0xe0, 0x53, 0x1b, 0x5a, 0x79, 0x12, 0x3a, 0xd5, 0x85, 0x9b, 0xd3, 0xb4, 0x17, 0xa1, - 0xf0, 0x83, 0x5d, 0x59, 0x6a, 0xdf, 0x91, 0x63, 0xb7, 0xc1, 0xba, 0x4c, 0x07, 0x5a, 0xd2, 0x04, - 0xf3, 0x21, 0x49, 0xf6, 0x8c, 0x13, 0xf3, 0x63, 0x68, 0x64, 0x50, 0x8c, 0x44, 0x13, 0xe6, 0x5c, - 0xcf, 0x63, 0xc9, 0x98, 0xa0, 0x17, 0x32, 0x06, 0x36, 0xe1, 0xe4, 0x82, 0x18, 0xe4, 0x49, 0xa8, - 0x79, 0x1b, 0xd6, 0xbe, 0x4b, 0xe1, 0xf2, 0x4a, 0x17, 0x96, 0x84, 0x45, 0x2c, 0x09, 0xd6, 0x3e, - 0xb4, 0xf2, 0x0c, 0x6f, 0x55, 0x8c, 0xae, 0xa7, 0xe5, 0x4c, 0xb2, 0x35, 0x51, 0x5f, 0x83, 0x92, - 0xef, 0xe1, 0x63, 0xa4, 0xe4, 0x7b, 0x99, 0x83, 0x28, 0x4d, 0x25, 0xc0, 0x16, 0x6c, 0x5e, 0x24, - 0x0c, 0xfd, 0x6c, 0xc0, 0xf2, 0xe3, 0xd0, 0x17, 0xfa, 0x02, 0x26, 0x81, 0xf9, 0x04, 0xcc, 0x34, - 0x78, 0x85, 0x4c, 0xfb, 0xd1, 0x80, 0xcd, 0x43, 0x1a, 0xc5, 0x81, 0x9a, 0x56, 0x23, 0x97, 0x91, - 0x50, 0x7c, 0x4d, 0x63, 0x16, 0xba, 0x41, 0x62, 0xf7, 0x07, 0xb0, 0x24, 0xf3, 0xc1, 0xe9, 0x31, - 0xe2, 0x0a, 0xe2, 0x39, 0x61, 0xf2, 0xa2, 0xaa, 0x4a, 0xf8, 0xbe, 0x46, 0xbf, 0xe1, 0xf2, 0xd5, - 0xe5, 0xf6, 0xa4, 0xd0, 0x74, 0xe3, 0x00, 0x0d, 0xa9, 0xe6, 0xf1, 0x25, 0x54, 0x06, 0xca, 0x32, - 0xc7, 0x0d, 0x7c, 0x57, 0x37, 0x90, 0xf2, 0xce, 0xca, 0xf4, 0x04, 0xbe, 0x2b, 0x89, 0x76, 0x59, - 0x6f, 0x55, 0x0b, 0xf3, 0x53, 0x68, 0xa6, 0x4a, 0xd5, 0x64, 0x50, 0x9d, 0x55, 0x3a, 0x1a, 0x29, - 0xda, 0x78, 0x5e, 0xbd, 0x09, 0x37, 0x2e, 0xf4, 0x0b, 0x43, 0xf8, 0x67, 0x43, 0x87, 0x0b, 0x03, - 0x9d, 0xf8, 0xfb, 0x73, 0x98, 0xd7, 0xfb, 0xf1, 0xd0, 0x2f, 0x30, 0x10, 0x37, 0x5d, 0x68, 0x5b, - 0xe9, 0x42, 0xdb, 0x8a, 0x22, 0x3a, 0x53, 0x10, 0x51, 0x59, 0xdf, 0x33, 0xf6, 0x4d, 0x46, 0xa0, - 0x07, 0x64, 0x40, 0x05, 0xc9, 0x1e, 0xfe, 0x1f, 0x0d, 0x68, 0x66, 0x71, 0x3c, 0xff, 0xcf, 0xa0, - 0xe1, 0x91, 0x88, 0x91, 0x9e, 0x52, 0x96, 0x4d, 0x85, 0x7b, 0xa5, 0x96, 0x61, 0x9b, 0x13, 0xf2, - 0xd8, 0xc6, 0x7b, 0x50, 0xc5, 0xc3, 0xc2, 0x9e, 0x51, 0xba, 0x4a, 0xcf, 0xc0, 0x03, 0xd6, 0x2b, - 0x79, 0x85, 0x5f, 0x84, 0x1e, 0x2d, 0x32, 0xb6, 0x0d, 0xad, 0x3c, 0x09, 0xfd, 0xdb, 0x18, 0x37, - 0xc9, 0x97, 0x2e, 0x3f, 0x64, 0x54, 0x6e, 0xf1, 0x12, 0xc6, 0xf7, 0xa0, 0x5d, 0x44, 0x44, 0xd6, - 0x7f, 0x18, 0x50, 0x3f, 0x22, 0xd9, 0x5b, 0xf1, 0xa6, 0x07, 0x5a, 0x70, 0x3a, 0xa5, 0xa2, 0x7c, - 0xbf, 0x0b, 0x6b, 0xea, 0x99, 0x20, 0x03, 0xc4, 0x44, 0xc1, 0x1b, 0x61, 0x45, 0x91, 0xa7, 0xab, - 0x65, 0xfe, 0xb9, 0x35, 0x5b, 0xf0, 0xdc, 0x6a, 0xc0, 0x72, 0xca, 0x0f, 0xf4, 0xee, 0x49, 0xda, - 0x77, 0x9b, 0x28, 0xbd, 0xe3, 0xc8, 0xbc, 0xa1, 0x9b, 0xd6, 0x75, 0xd8, 0x28, 0x14, 0x86, 0xba, - 0x7e, 0x2f, 0xeb, 0x7c, 0xa6, 0x81, 0xed, 0x86, 0xde, 0x43, 0x22, 0x32, 0xa3, 0x86, 0xf9, 0x3d, - 0xac, 0x70, 0x41, 0xa3, 0xb4, 0xf3, 0xce, 0x80, 0x7a, 0xc9, 0xeb, 0xfa, 0x76, 0xc1, 0x04, 0x93, - 0x6d, 0x8a, 0xd4, 0x23, 0x76, 0x83, 0xe7, 0x41, 0xf9, 0x78, 0xb9, 0x75, 0xa9, 0x01, 0xe3, 0x1f, - 0x22, 0xaa, 0x27, 0xa3, 0x2e, 0xf3, 0x3d, 0xe7, 0x4a, 0xb3, 0x93, 0xca, 0xf7, 0x8a, 0xe6, 0xc0, - 0x1f, 0x83, 0x7e, 0x3d, 0x1e, 0x8b, 0x74, 0x8a, 0x7f, 0xf0, 0x3a, 0xa3, 0xf3, 0xf3, 0x11, 0xe6, - 0x61, 0xb6, 0x90, 0xc8, 0x49, 0x67, 0x9a, 0x70, 0x85, 0x8a, 0x7c, 0x04, 0xd5, 0x7b, 0x6e, 0xef, - 0x34, 0x1e, 0x4f, 0xb2, 0x5b, 0x50, 0xee, 0xd1, 0xb0, 0x17, 0x33, 0x46, 0xc2, 0xde, 0x08, 0x6b, - 0x6f, 0x1a, 0x92, 0x3b, 0xd4, 0x73, 0x54, 0xa7, 0x0b, 0xbe, 0x61, 0xd3, 0x90, 0x75, 0x17, 0x6a, - 0x89, 0x50, 0x34, 0xe1, 0x36, 0xcc, 0x91, 0xe1, 0x24, 0x59, 0x6a, 0x9d, 0xe4, 0x1f, 0x32, 0x7b, - 0x12, 0xb5, 0x35, 0x11, 0x3b, 0xad, 0xa0, 0x8c, 0xec, 0x33, 0x3a, 0xc8, 0xd8, 0x65, 0xed, 0xca, - 0x6b, 0x9a, 0xa3, 0xbd, 0x91, 0xf8, 0x26, 0x98, 0x47, 0x81, 0x3b, 0x24, 0xd9, 0xf9, 0x75, 0x1f, - 0x1a, 0x19, 0xf4, 0x6d, 0xc7, 0x63, 0x13, 0xea, 0xf2, 0xe4, 0x94, 0xac, 0x44, 0xb6, 0xbc, 0x57, - 0x13, 0x0c, 0x73, 0xfd, 0x7b, 0x3d, 0x27, 0x2a, 0xf0, 0xdd, 0x8e, 0x81, 0x77, 0xe5, 0xb4, 0x36, - 0x2d, 0xf9, 0x0a, 0x49, 0xa0, 0xcc, 0x74, 0x99, 0xc8, 0xd8, 0x2e, 0xa3, 0x95, 0x02, 0xd1, 0xf8, - 0xdf, 0xc2, 0xc6, 0x04, 0x7d, 0xe7, 0xe3, 0xde, 0x26, 0xbc, 0x57, 0x2c, 0x1d, 0xb5, 0x9b, 0xfa, - 0x97, 0x51, 0x49, 0x1d, 0x9f, 0xdf, 0xcf, 0xf4, 0xaf, 0x96, 0x88, 0x5d, 0x3a, 0xe4, 0xfd, 0xc9, - 0x80, 0xba, 0x6c, 0x71, 0x69, 0x3f, 0x7f, 0x42, 0x0d, 0x18, 0x87, 0xac, 0x6c, 0xc0, 0xe5, 0x70, - 0x2e, 0x81, 0x82, 0xe6, 0x24, 0x87, 0xf3, 0x1c, 0x09, 0xd9, 0x1e, 0x4f, 0x68, 0xff, 0x6b, 0xe9, - 0xde, 0x80, 0xf5, 0x02, 0x51, 0x5a, 0xcf, 0xbd, 0x4f, 0x7e, 0xe8, 0x0c, 0x7d, 0x41, 0x38, 0xef, - 0xf8, 0x74, 0x5b, 0x7f, 0x6d, 0xf7, 0xe9, 0xf6, 0x50, 0x6c, 0xab, 0x7f, 0xb5, 0x6e, 0xe7, 0x7e, - 0x9b, 0xe9, 0xce, 0x2b, 0xc2, 0x67, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x96, 0x1e, 0xcb, 0x36, - 0xf4, 0x1d, 0x00, 0x00, + 0xf5, 0x1f, 0x52, 0x1f, 0x96, 0x0e, 0x3f, 0x44, 0x81, 0x94, 0x48, 0x51, 0xb1, 0x2c, 0xc3, 0x4e, + 0xe2, 0x7f, 0x32, 0x7f, 0x2a, 0x91, 0x13, 0x4f, 0x26, 0x69, 0x3b, 0x95, 0x6d, 0xc9, 0x76, 0x2c, + 0xc7, 0x0a, 0xe4, 0x8f, 0x4c, 0xa6, 0x53, 0x0c, 0x48, 0xac, 0x28, 0x8c, 0x40, 0x2c, 0xbc, 0xbb, + 0xa4, 0xc4, 0x9b, 0x3e, 0x42, 0xfb, 0x02, 0x9d, 0xde, 0x74, 0xa6, 0xbd, 0xef, 0x43, 0xf4, 0x11, + 0xd2, 0x47, 0xe9, 0x45, 0x2f, 0xda, 0xd9, 0xdd, 0x03, 0x10, 0x20, 0x20, 0x59, 0x56, 0xdd, 0x99, + 0xdc, 0x68, 0xb0, 0xbf, 0xb3, 0xe7, 0x73, 0xcf, 0x9e, 0x73, 0x96, 0x82, 0xa6, 0x70, 0xba, 0x3e, + 0x11, 0x03, 0x27, 0x70, 0xfa, 0x84, 0xb9, 0x8e, 0x70, 0x3a, 0x21, 0xa3, 0x82, 0x1a, 0xcb, 0x19, + 0x42, 0xbb, 0xf4, 0x66, 0x48, 0xd8, 0x58, 0xd3, 0xdb, 0x55, 0x41, 0x43, 0x3a, 0xd9, 0xdf, 0x5e, + 0x61, 0x24, 0xf4, 0xbd, 0x9e, 0x23, 0x3c, 0x1a, 0x24, 0xe0, 0x8a, 0x4f, 0xfb, 0x43, 0xe1, 0xf9, + 0x7a, 0x69, 0xfe, 0xbb, 0x00, 0x4b, 0x2f, 0xa4, 0xe0, 0x87, 0xe4, 0xc8, 0x0b, 0x3c, 0xb9, 0xd9, + 0x30, 0x60, 0x36, 0x70, 0x06, 0xa4, 0x55, 0xd8, 0x2c, 0xdc, 0x59, 0xb4, 0xd4, 0xb7, 0xb1, 0x0a, + 0xf3, 0xbc, 0x77, 0x4c, 0x06, 0x4e, 0xab, 0xa8, 0x50, 0x5c, 0x19, 0x2d, 0xb8, 0xd6, 0xa3, 0xfe, + 0x70, 0x10, 0xf0, 0xd6, 0xcc, 0xe6, 0xcc, 0x9d, 0x45, 0x2b, 0x5a, 0x1a, 0x1d, 0xa8, 0x87, 0xcc, + 0x1b, 0x38, 0x6c, 0x6c, 0x9f, 0x90, 0xb1, 0x1d, 0xed, 0x9a, 0x55, 0xbb, 0x96, 0x91, 0xf4, 0x94, + 0x8c, 0x1f, 0xe0, 0x7e, 0x03, 0x66, 0xc5, 0x38, 0x24, 0xad, 0x39, 0xad, 0x55, 0x7e, 0x1b, 0x37, + 0xa0, 0x24, 0x4d, 0xb7, 0x7d, 0x12, 0xf4, 0xc5, 0x71, 0x6b, 0x7e, 0xb3, 0x70, 0x67, 0xd6, 0x02, + 0x09, 0xed, 0x2b, 0xc4, 0x58, 0x87, 0x45, 0x46, 0x4f, 0xed, 0x1e, 0x1d, 0x06, 0xa2, 0x75, 0x4d, + 0x91, 0x17, 0x18, 0x3d, 0x7d, 0x20, 0xd7, 0xc6, 0x6d, 0x98, 0x3f, 0xf2, 0x88, 0xef, 0xf2, 0xd6, + 0xc2, 0xe6, 0xcc, 0x9d, 0xd2, 0x76, 0xb9, 0xa3, 0xe3, 0xb5, 0x27, 0x41, 0x0b, 0x69, 0xe6, 0x5f, + 0x0a, 0x50, 0x3b, 0x54, 0xce, 0x24, 0x42, 0xf0, 0x31, 0x2c, 0x49, 0x2d, 0x5d, 0x87, 0x13, 0x1b, + 0xfd, 0xd6, 0xd1, 0xa8, 0x46, 0xb0, 0x66, 0x31, 0x9e, 0x83, 0x3e, 0x17, 0xdb, 0x8d, 0x99, 0x79, + 0xab, 0xa8, 0xd4, 0x99, 0x9d, 0xec, 0x51, 0x4e, 0x85, 0xda, 0xaa, 0x89, 0x34, 0xc0, 0x65, 0x40, + 0x47, 0x84, 0x71, 0x8f, 0x06, 0xad, 0x19, 0xa5, 0x31, 0x5a, 0x4a, 0x43, 0x0d, 0xad, 0xf5, 0xc1, + 0xb1, 0x13, 0xf4, 0x89, 0x45, 0xf8, 0xd0, 0x17, 0xc6, 0x63, 0xa8, 0x74, 0xc9, 0x11, 0x65, 0x29, + 0x43, 0x4b, 0xdb, 0xb7, 0x72, 0xb4, 0x4f, 0xbb, 0x69, 0x95, 0x35, 0x27, 0xfa, 0xb2, 0x07, 0x65, + 0xe7, 0x48, 0x10, 0x66, 0x27, 0x4e, 0xfa, 0x92, 0x82, 0x4a, 0x8a, 0x51, 0xc3, 0xe6, 0x3f, 0x0b, + 0x50, 0x7d, 0xc9, 0x09, 0x3b, 0x20, 0x6c, 0xe0, 0x71, 0x8e, 0x29, 0x75, 0x4c, 0xb9, 0x88, 0x52, + 0x4a, 0x7e, 0x4b, 0x6c, 0xc8, 0x09, 0xc3, 0x84, 0x52, 0xdf, 0xc6, 0xa7, 0xb0, 0x1c, 0x3a, 0x9c, + 0x9f, 0x52, 0xe6, 0xda, 0xbd, 0x63, 0xd2, 0x3b, 0xe1, 0xc3, 0x81, 0x8a, 0xc3, 0xac, 0x55, 0x8b, + 0x08, 0x0f, 0x10, 0x37, 0xbe, 0x07, 0x08, 0x99, 0x37, 0xf2, 0x7c, 0xd2, 0x27, 0x3a, 0xb1, 0x4a, + 0xdb, 0x9f, 0xe7, 0x58, 0x9b, 0xb6, 0xa5, 0x73, 0x10, 0xf3, 0xec, 0x06, 0x82, 0x8d, 0xad, 0x84, + 0x90, 0xf6, 0x2f, 0x61, 0x69, 0x8a, 0x6c, 0xd4, 0x60, 0xe6, 0x84, 0x8c, 0xd1, 0x72, 0xf9, 0x69, + 0x34, 0x60, 0x6e, 0xe4, 0xf8, 0x43, 0x82, 0x96, 0xeb, 0xc5, 0xd7, 0xc5, 0xaf, 0x0a, 0xe6, 0x4f, + 0x05, 0x28, 0x3f, 0xec, 0xbe, 0xc5, 0xef, 0x2a, 0x14, 0xdd, 0x2e, 0xf2, 0x16, 0xdd, 0x6e, 0x1c, + 0x87, 0x99, 0x44, 0x1c, 0x9e, 0xe7, 0xb8, 0xb6, 0x95, 0xe3, 0x5a, 0x52, 0xd9, 0xff, 0xd2, 0xb1, + 0x3f, 0x17, 0xa0, 0x34, 0xd1, 0xc4, 0x8d, 0x7d, 0xa8, 0x49, 0x3b, 0xed, 0x70, 0x82, 0xb5, 0x0a, + 0xca, 0xca, 0x9b, 0x6f, 0x3d, 0x00, 0x6b, 0x69, 0x98, 0x5a, 0x73, 0x63, 0x0f, 0xaa, 0x6e, 0x37, + 0x25, 0x4b, 0xdf, 0xa0, 0x1b, 0x6f, 0xf1, 0xd8, 0xaa, 0xb8, 0x89, 0x15, 0x37, 0x3f, 0x86, 0xd2, + 0x81, 0x17, 0xf4, 0x2d, 0xf2, 0x66, 0x48, 0xb8, 0x90, 0x57, 0x29, 0x74, 0xc6, 0x3e, 0x75, 0x5c, + 0x74, 0x32, 0x5a, 0x9a, 0x77, 0xa0, 0xac, 0x37, 0xf2, 0x90, 0x06, 0x9c, 0x5c, 0xb0, 0xf3, 0x13, + 0x28, 0x1f, 0xfa, 0x84, 0x84, 0x91, 0xcc, 0x36, 0x2c, 0xb8, 0x43, 0xa6, 0x8a, 0xaa, 0xda, 0x3a, + 0x63, 0xc5, 0x6b, 0x73, 0x09, 0x2a, 0xb8, 0x57, 0x8b, 0x35, 0xff, 0x51, 0x00, 0x63, 0xf7, 0x8c, + 0xf4, 0x86, 0x82, 0x3c, 0xa6, 0xf4, 0x24, 0x92, 0x91, 0x57, 0x5f, 0x37, 0x00, 0x42, 0x87, 0x39, + 0x03, 0x22, 0x08, 0xd3, 0xee, 0x2f, 0x5a, 0x09, 0xc4, 0x38, 0x80, 0x45, 0x72, 0x26, 0x98, 0x63, + 0x93, 0x60, 0xa4, 0x2a, 0x6d, 0x69, 0xfb, 0x6e, 0x4e, 0x74, 0xb2, 0xda, 0x3a, 0xbb, 0x92, 0x6d, + 0x37, 0x18, 0xe9, 0x9c, 0x58, 0x20, 0xb8, 0x6c, 0x7f, 0x03, 0x95, 0x14, 0xe9, 0x9d, 0xf2, 0xe1, + 0x08, 0xea, 0x29, 0x55, 0x18, 0xc7, 0x1b, 0x50, 0x22, 0x67, 0x9e, 0xb0, 0xb9, 0x70, 0xc4, 0x90, + 0x63, 0x80, 0x40, 0x42, 0x87, 0x0a, 0x51, 0x6d, 0x44, 0xb8, 0x74, 0x28, 0xe2, 0x36, 0xa2, 0x56, + 0x88, 0x13, 0x16, 0xdd, 0x02, 0x5c, 0x99, 0x23, 0xa8, 0x3d, 0x22, 0x42, 0xd7, 0x95, 0x28, 0x7c, + 0xab, 0x30, 0xaf, 0x1c, 0xd7, 0x19, 0xb7, 0x68, 0xe1, 0xca, 0xb8, 0x05, 0x15, 0x2f, 0xe8, 0xf9, + 0x43, 0x97, 0xd8, 0x23, 0x8f, 0x9c, 0x72, 0xa5, 0x62, 0xc1, 0x2a, 0x23, 0xf8, 0x4a, 0x62, 0xc6, + 0x87, 0x50, 0x25, 0x67, 0x7a, 0x13, 0x0a, 0xd1, 0x6d, 0xab, 0x82, 0xa8, 0x2a, 0xd0, 0xdc, 0x24, + 0xb0, 0x9c, 0xd0, 0x8b, 0xde, 0x1d, 0xc0, 0xb2, 0xae, 0x8c, 0x89, 0x62, 0xff, 0x2e, 0xd5, 0xb6, + 0xc6, 0xa7, 0x10, 0xb3, 0x09, 0x2b, 0x8f, 0x88, 0x48, 0xa4, 0x30, 0xfa, 0x68, 0xfe, 0x08, 0xab, + 0xd3, 0x04, 0x34, 0xe2, 0xd7, 0x50, 0x4a, 0x5f, 0x3a, 0xa9, 0x7e, 0x23, 0x47, 0x7d, 0x92, 0x39, + 0xc9, 0x62, 0x36, 0xc0, 0x38, 0x24, 0xc2, 0x22, 0x8e, 0xfb, 0x3c, 0xf0, 0xc7, 0x91, 0xc6, 0x15, + 0xa8, 0xa7, 0x50, 0x4c, 0xe1, 0x09, 0xfc, 0x9a, 0x79, 0x82, 0x44, 0xbb, 0x57, 0xa1, 0x91, 0x86, + 0x71, 0xfb, 0xb7, 0xb0, 0xac, 0x9b, 0xd3, 0x8b, 0x71, 0x18, 0x6d, 0x36, 0xbe, 0x84, 0x92, 0x36, + 0xcf, 0x56, 0x0d, 0x5e, 0x9a, 0x5c, 0xdd, 0x6e, 0x74, 0xe2, 0x79, 0x45, 0xc5, 0x5c, 0x28, 0x0e, + 0x10, 0xf1, 0xb7, 0xb4, 0x33, 0x29, 0x6b, 0x62, 0x90, 0x45, 0x8e, 0x18, 0xe1, 0xc7, 0x32, 0xa5, + 0x92, 0x06, 0xa5, 0x61, 0xdc, 0xde, 0x84, 0x15, 0x6b, 0x18, 0x3c, 0x26, 0x8e, 0x2f, 0x8e, 0x55, + 0xe3, 0x88, 0x18, 0x5a, 0xb0, 0x3a, 0x4d, 0x40, 0x96, 0x2f, 0xa0, 0xf5, 0xa4, 0x1f, 0x50, 0x46, + 0x34, 0x71, 0x97, 0x31, 0xca, 0x52, 0x25, 0x45, 0x08, 0xc2, 0x82, 0x49, 0xa1, 0x50, 0x4b, 0x73, + 0x1d, 0xd6, 0x72, 0xb8, 0x50, 0xe4, 0xd7, 0xd2, 0x68, 0x59, 0x4f, 0xd2, 0x99, 0x7c, 0x0b, 0x2a, + 0xa7, 0x8e, 0x27, 0xec, 0x90, 0xf2, 0x49, 0x32, 0x2d, 0x5a, 0x65, 0x09, 0x1e, 0x20, 0xa6, 0x3d, + 0x4b, 0xf2, 0xa2, 0xcc, 0x6d, 0x58, 0x3d, 0x60, 0xe4, 0xc8, 0xf7, 0xfa, 0xc7, 0x53, 0x17, 0x44, + 0xce, 0x64, 0x2a, 0x70, 0xd1, 0x0d, 0x89, 0x96, 0x66, 0x1f, 0x9a, 0x19, 0x1e, 0xcc, 0xab, 0x7d, + 0xa8, 0xea, 0x5d, 0x36, 0x53, 0x73, 0x45, 0x54, 0xcf, 0x3f, 0x3c, 0x37, 0xb3, 0x93, 0x53, 0x88, + 0x55, 0xe9, 0x25, 0x56, 0xdc, 0xfc, 0x57, 0x01, 0x8c, 0x9d, 0x30, 0xf4, 0xc7, 0x69, 0xcb, 0x6a, + 0x30, 0xc3, 0xdf, 0xf8, 0x51, 0x89, 0xe1, 0x6f, 0x7c, 0x59, 0x62, 0x8e, 0x28, 0xeb, 0x11, 0xbc, + 0xac, 0x7a, 0x21, 0xc7, 0x00, 0xc7, 0xf7, 0xe9, 0xa9, 0x9d, 0x98, 0x61, 0x55, 0x65, 0x58, 0xb0, + 0x6a, 0x8a, 0x60, 0x4d, 0xf0, 0xec, 0x00, 0x34, 0xfb, 0xbe, 0x06, 0xa0, 0xb9, 0x2b, 0x0e, 0x40, + 0x7f, 0x2d, 0x40, 0x3d, 0xe5, 0x3d, 0xc6, 0xf8, 0xe7, 0x37, 0xaa, 0xd5, 0x61, 0x79, 0x9f, 0xf6, + 0x4e, 0x74, 0xd5, 0x8b, 0xae, 0x46, 0x03, 0x8c, 0x24, 0x38, 0xb9, 0x78, 0x2f, 0x03, 0x3f, 0xb3, + 0x79, 0x15, 0x1a, 0x69, 0x18, 0xb7, 0xff, 0xad, 0x00, 0x2d, 0x6c, 0x11, 0x7b, 0x44, 0xf4, 0x8e, + 0x77, 0xf8, 0xc3, 0x6e, 0x9c, 0x07, 0x0d, 0x98, 0x53, 0xa3, 0xb8, 0x0a, 0x40, 0xd9, 0xd2, 0x0b, + 0xa3, 0x09, 0xd7, 0xdc, 0xae, 0xad, 0x5a, 0x23, 0x76, 0x07, 0xb7, 0xfb, 0x9d, 0x6c, 0x8e, 0x6b, + 0xb0, 0x30, 0x70, 0xce, 0x6c, 0x46, 0x4f, 0x39, 0x0e, 0x83, 0xd7, 0x06, 0xce, 0x99, 0x45, 0x4f, + 0xb9, 0x1a, 0xd4, 0x3d, 0xae, 0x26, 0xf0, 0xae, 0x17, 0xf8, 0xb4, 0xcf, 0xd5, 0xf1, 0x2f, 0x58, + 0x55, 0x84, 0xef, 0x6b, 0x54, 0xde, 0x35, 0xa6, 0xae, 0x51, 0xf2, 0x70, 0x17, 0xac, 0x32, 0x4b, + 0xdc, 0x2d, 0xf3, 0x11, 0xac, 0xe5, 0xd8, 0x8c, 0xa7, 0xf7, 0x09, 0xcc, 0xeb, 0xab, 0x81, 0xc7, + 0x66, 0xe0, 0x73, 0xe2, 0x7b, 0xf9, 0x17, 0xaf, 0x01, 0xee, 0x30, 0x7f, 0x5f, 0x80, 0xeb, 0x69, + 0x49, 0x3b, 0xbe, 0x2f, 0x07, 0x30, 0xfe, 0xfe, 0x43, 0x90, 0xf1, 0x6c, 0x36, 0xc7, 0xb3, 0x7d, + 0xd8, 0x38, 0xcf, 0x9e, 0x2b, 0xb8, 0xf7, 0x74, 0xfa, 0x6c, 0x77, 0xc2, 0xf0, 0x62, 0xc7, 0x92, + 0xf6, 0x17, 0x53, 0xf6, 0x67, 0x83, 0xae, 0x84, 0x5d, 0xc1, 0xaa, 0x36, 0xb4, 0x12, 0x75, 0x41, + 0x4f, 0x1c, 0x51, 0x9a, 0xee, 0xc3, 0x5a, 0x0e, 0x0d, 0x95, 0x6c, 0xc9, 0xe9, 0x23, 0x9e, 0x58, + 0x4a, 0xdb, 0xcd, 0xce, 0xf4, 0xdb, 0x19, 0x19, 0x70, 0x9b, 0xbc, 0x0b, 0xcf, 0x1c, 0x2e, 0xaf, + 0x51, 0x4a, 0xc9, 0x33, 0x68, 0xa4, 0x61, 0x94, 0xff, 0xe5, 0x94, 0xfc, 0xeb, 0x19, 0xf9, 0x29, + 0xb6, 0x48, 0x4b, 0x13, 0x56, 0x34, 0x1e, 0xf5, 0x82, 0x48, 0xcf, 0x17, 0xb0, 0x3a, 0x4d, 0x40, + 0x4d, 0x6d, 0x58, 0x98, 0x6a, 0x26, 0xf1, 0x5a, 0x72, 0xbd, 0x76, 0x3c, 0xb1, 0x47, 0xa7, 0xe5, + 0x5d, 0xc8, 0xb5, 0x06, 0xcd, 0x0c, 0x17, 0x5e, 0xf1, 0x16, 0xac, 0x1e, 0x0a, 0x1a, 0x26, 0xe2, + 0x1a, 0x19, 0xb8, 0x06, 0xcd, 0x0c, 0x05, 0x99, 0x7e, 0x0b, 0xd7, 0xa7, 0x48, 0xcf, 0xbc, 0xc0, + 0x1b, 0x0c, 0x07, 0x97, 0x30, 0xc6, 0xb8, 0x09, 0xaa, 0x37, 0xda, 0xc2, 0x1b, 0x90, 0x68, 0x88, + 0x9c, 0xb1, 0x4a, 0x12, 0x7b, 0xa1, 0x21, 0xf3, 0x17, 0xb0, 0x71, 0x9e, 0xfc, 0x4b, 0xc4, 0x48, + 0x19, 0xee, 0x30, 0x91, 0xe3, 0x53, 0x1b, 0x5a, 0x59, 0x12, 0x3a, 0xd5, 0x85, 0x9b, 0xd3, 0xb4, + 0x97, 0x81, 0xf0, 0xfc, 0x1d, 0x59, 0x6a, 0xdf, 0x93, 0x63, 0xb7, 0xc1, 0xbc, 0x48, 0x07, 0x5a, + 0xd2, 0x00, 0xe3, 0x11, 0x89, 0xf6, 0xc4, 0x89, 0xf9, 0x29, 0xd4, 0x53, 0x28, 0x46, 0xa2, 0x01, + 0x73, 0x8e, 0xeb, 0xb2, 0x68, 0x4c, 0xd0, 0x0b, 0x19, 0x03, 0x8b, 0x70, 0x72, 0x4e, 0x0c, 0xb2, + 0x24, 0xd4, 0xbc, 0x05, 0xcd, 0x57, 0x09, 0x5c, 0x5e, 0xe9, 0xdc, 0x92, 0xb0, 0x88, 0x25, 0xc1, + 0xdc, 0x83, 0x56, 0x96, 0xe1, 0x4a, 0xc5, 0xe8, 0x7a, 0x52, 0xce, 0x24, 0x5b, 0x23, 0xf5, 0x55, + 0x28, 0x7a, 0x2e, 0x3e, 0x46, 0x8a, 0x9e, 0x9b, 0x3a, 0x88, 0xe2, 0x54, 0x02, 0x6c, 0xc2, 0xc6, + 0x79, 0xc2, 0xd0, 0xcf, 0x3a, 0x2c, 0x3f, 0x09, 0x3c, 0xa1, 0x2f, 0x60, 0x14, 0x98, 0xcf, 0xc0, + 0x48, 0x82, 0x97, 0xc8, 0xb4, 0x9f, 0x0a, 0xb0, 0x71, 0x40, 0xc3, 0xa1, 0xaf, 0xa6, 0xd5, 0xd0, + 0x61, 0x24, 0x10, 0xdf, 0xd2, 0x21, 0x0b, 0x1c, 0x3f, 0xb2, 0xfb, 0x23, 0x58, 0x92, 0xf9, 0x60, + 0xf7, 0x18, 0x71, 0x04, 0x71, 0xed, 0x20, 0x7a, 0x51, 0x55, 0x24, 0xfc, 0x40, 0xa3, 0xdf, 0x71, + 0xf9, 0xea, 0x72, 0x7a, 0x52, 0x68, 0xb2, 0x71, 0x80, 0x86, 0x54, 0xf3, 0xf8, 0x0a, 0xca, 0x03, + 0x65, 0x99, 0xed, 0xf8, 0x9e, 0xa3, 0x1b, 0x48, 0x69, 0x7b, 0x65, 0x7a, 0x02, 0xdf, 0x91, 0x44, + 0xab, 0xa4, 0xb7, 0xaa, 0x85, 0xf1, 0x39, 0x34, 0x12, 0xa5, 0x6a, 0x32, 0xa8, 0xce, 0x2a, 0x1d, + 0xf5, 0x04, 0x2d, 0x9e, 0x57, 0x6f, 0xc2, 0x8d, 0x73, 0xfd, 0xc2, 0x10, 0xfe, 0xa9, 0xa0, 0xc3, + 0x85, 0x81, 0x8e, 0xfc, 0xfd, 0x7f, 0x98, 0xd7, 0xfb, 0xf1, 0xd0, 0xcf, 0x31, 0x10, 0x37, 0x9d, + 0x6b, 0x5b, 0xf1, 0x5c, 0xdb, 0xf2, 0x22, 0x3a, 0x93, 0x13, 0x51, 0x59, 0xdf, 0x53, 0xf6, 0x4d, + 0x46, 0xa0, 0x87, 0x64, 0x40, 0x05, 0x49, 0x1f, 0xfe, 0x1f, 0x0a, 0xd0, 0x48, 0xe3, 0x78, 0xfe, + 0x77, 0xa1, 0xee, 0x92, 0x90, 0x91, 0x9e, 0x52, 0x96, 0x4e, 0x85, 0xfb, 0xc5, 0x56, 0xc1, 0x32, + 0x26, 0xe4, 0xd8, 0xc6, 0xfb, 0x50, 0xc1, 0xc3, 0xc2, 0x9e, 0x51, 0xbc, 0x4c, 0xcf, 0xc0, 0x03, + 0xd6, 0x2b, 0x79, 0x85, 0x5f, 0x06, 0x2e, 0xcd, 0x33, 0xb6, 0x0d, 0xad, 0x2c, 0x09, 0xfd, 0x5b, + 0x8f, 0x9b, 0xe4, 0x6b, 0x87, 0x1f, 0x30, 0x2a, 0xb7, 0xb8, 0x11, 0xe3, 0x07, 0xd0, 0xce, 0x23, + 0x22, 0xeb, 0xdf, 0x0b, 0x50, 0x3b, 0x24, 0xe9, 0x5b, 0xf1, 0xae, 0x07, 0x9a, 0x73, 0x3a, 0xc5, + 0xbc, 0x7c, 0xbf, 0x07, 0x4d, 0xf5, 0x4c, 0x90, 0x01, 0x62, 0x22, 0xe7, 0x8d, 0xb0, 0xa2, 0xc8, + 0xd3, 0xd5, 0x32, 0xfb, 0xdc, 0x9a, 0xcd, 0x79, 0x6e, 0xd5, 0x61, 0x39, 0xe1, 0x07, 0x7a, 0xf7, + 0x34, 0xe9, 0xbb, 0x45, 0x94, 0xde, 0x38, 0x32, 0xef, 0xe8, 0xa6, 0x79, 0x1d, 0xd6, 0x73, 0x85, + 0xa1, 0xae, 0xdf, 0xc9, 0x3a, 0x9f, 0x6a, 0x60, 0x3b, 0x81, 0xfb, 0x88, 0x88, 0xd4, 0xa8, 0x61, + 0xfc, 0x00, 0x2b, 0x5c, 0xd0, 0x30, 0xe9, 0xbc, 0x3d, 0xa0, 0x6e, 0xf4, 0xba, 0xbe, 0x9d, 0x33, + 0xc1, 0xa4, 0x9b, 0x22, 0x75, 0x89, 0x55, 0xe7, 0x59, 0x50, 0x3e, 0x5e, 0x6e, 0x5d, 0x68, 0x40, + 0xfc, 0x43, 0x44, 0xe5, 0x78, 0xdc, 0x65, 0x9e, 0x6b, 0x5f, 0x6a, 0x76, 0x52, 0xf9, 0x5e, 0xd6, + 0x1c, 0xf8, 0x63, 0xd0, 0xaf, 0xe2, 0xb1, 0x48, 0xa7, 0xf8, 0x47, 0x6f, 0x33, 0x3a, 0x3b, 0x1f, + 0x61, 0x1e, 0xa6, 0x0b, 0x89, 0x9c, 0x74, 0xa6, 0x09, 0x97, 0xa8, 0xc8, 0x87, 0x50, 0xb9, 0xef, + 0xf4, 0x4e, 0x86, 0xf1, 0x24, 0xbb, 0x09, 0xa5, 0x1e, 0x0d, 0x7a, 0x43, 0xc6, 0x48, 0xd0, 0x1b, + 0x63, 0xed, 0x4d, 0x42, 0x72, 0x87, 0x7a, 0x8e, 0xea, 0x74, 0xc1, 0x37, 0x6c, 0x12, 0x32, 0xef, + 0x41, 0x35, 0x12, 0x8a, 0x26, 0xdc, 0x86, 0x39, 0x32, 0x9a, 0x24, 0x4b, 0xb5, 0x13, 0xfd, 0x43, + 0x66, 0x57, 0xa2, 0x96, 0x26, 0x62, 0xa7, 0x15, 0x94, 0x91, 0x3d, 0x46, 0x07, 0x29, 0xbb, 0xcc, + 0x1d, 0x79, 0x4d, 0x33, 0xb4, 0x77, 0x12, 0xdf, 0x00, 0xe3, 0xd0, 0x77, 0x46, 0x24, 0x3d, 0xbf, + 0xee, 0x41, 0x3d, 0x85, 0x5e, 0x75, 0x3c, 0x36, 0xa0, 0x26, 0x4f, 0x4e, 0xc9, 0x8a, 0x64, 0xcb, + 0x7b, 0x35, 0xc1, 0x30, 0xd7, 0x7f, 0xd0, 0x73, 0xa2, 0x02, 0xdf, 0xef, 0x18, 0x78, 0x4f, 0x4e, + 0x6b, 0xd3, 0x92, 0x2f, 0x91, 0x04, 0xca, 0x4c, 0x87, 0x89, 0x94, 0xed, 0x32, 0x5a, 0x09, 0x10, + 0x8d, 0xff, 0x0d, 0xac, 0x4f, 0xd0, 0xf7, 0x3e, 0xee, 0x6d, 0xc0, 0x07, 0xf9, 0xd2, 0x51, 0xbb, + 0xa1, 0x7f, 0x19, 0x95, 0xd4, 0xf8, 0xfc, 0xfe, 0x4f, 0xff, 0x6a, 0x89, 0xd8, 0x85, 0x43, 0xde, + 0x1f, 0x0b, 0x50, 0x93, 0x2d, 0x2e, 0xe9, 0xe7, 0xcf, 0xa8, 0x01, 0xe3, 0x90, 0x95, 0x0e, 0xb8, + 0x1c, 0xce, 0x25, 0x90, 0xd3, 0x9c, 0xe4, 0x70, 0x9e, 0x21, 0x21, 0xdb, 0x93, 0x09, 0xed, 0xbf, + 0x2d, 0xdd, 0xeb, 0xb0, 0x96, 0x23, 0x2a, 0xce, 0x87, 0xf2, 0xab, 0xb7, 0x4e, 0xbd, 0x32, 0x2d, + 0x4e, 0x29, 0x3b, 0x39, 0xf2, 0xe9, 0x69, 0x34, 0x7c, 0x46, 0x6b, 0x49, 0x3b, 0x21, 0x63, 0x1e, + 0x3a, 0x3d, 0x82, 0xbf, 0x83, 0xc7, 0x6b, 0xf3, 0x1b, 0xa8, 0xbc, 0xba, 0xea, 0x88, 0x7c, 0xff, + 0xb3, 0x1f, 0x3b, 0x23, 0x4f, 0x10, 0xce, 0x3b, 0x1e, 0xdd, 0xd2, 0x5f, 0x5b, 0x7d, 0xba, 0x35, + 0x12, 0x5b, 0xea, 0xbf, 0xc0, 0x5b, 0x99, 0x9f, 0x8d, 0xba, 0xf3, 0x8a, 0x70, 0xf7, 0x3f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x82, 0x1c, 0x56, 0x23, 0x8f, 0x1e, 0x00, 0x00, } diff --git a/go/vt/proto/tabletmanagerservice/tabletmanagerservice.pb.go b/go/vt/proto/tabletmanagerservice/tabletmanagerservice.pb.go index ac5081933d4..28e717a9db3 100644 --- a/go/vt/proto/tabletmanagerservice/tabletmanagerservice.pb.go +++ b/go/vt/proto/tabletmanagerservice/tabletmanagerservice.pb.go @@ -29,77 +29,78 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package func init() { proto.RegisterFile("tabletmanagerservice.proto", fileDescriptor_9ee75fe63cfd9360) } var fileDescriptor_9ee75fe63cfd9360 = []byte{ - // 1116 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xdb, 0x6f, 0x1b, 0x45, - 0x14, 0xc6, 0x89, 0x04, 0x95, 0x98, 0x72, 0x1d, 0x2a, 0x2a, 0x05, 0x89, 0x5b, 0x13, 0x28, 0x71, - 0xb1, 0x7b, 0xa1, 0xbc, 0xbb, 0x97, 0xa4, 0x41, 0x8d, 0x30, 0x76, 0x43, 0x10, 0x48, 0x95, 0x26, - 0xf6, 0x89, 0xbd, 0x64, 0xbd, 0xb3, 0xcc, 0x8c, 0x2d, 0xf2, 0x84, 0xd4, 0x57, 0x24, 0xfe, 0x66, - 0xb4, 0xeb, 0x9d, 0xdd, 0x33, 0xbb, 0x67, 0x8f, 0x37, 0x6f, 0x96, 0xbf, 0xdf, 0x9c, 0x6f, 0x2e, - 0x67, 0xce, 0xcc, 0x8e, 0xd8, 0x75, 0xea, 0x3c, 0x06, 0xb7, 0x54, 0x89, 0x9a, 0x83, 0xb1, 0x60, - 0xd6, 0xd1, 0x14, 0xfa, 0xa9, 0xd1, 0x4e, 0xcb, 0x5b, 0x94, 0xb6, 0x7b, 0x3b, 0xf8, 0x77, 0xa6, - 0x9c, 0xda, 0xe0, 0x0f, 0xdf, 0xf4, 0xc4, 0xfb, 0xaf, 0x72, 0xed, 0x64, 0xa3, 0xc9, 0x63, 0xf1, - 0xf6, 0x28, 0x4a, 0xe6, 0xf2, 0xf3, 0x7e, 0xb3, 0x4d, 0x26, 0x8c, 0xe1, 0xaf, 0x15, 0x58, 0xb7, - 0xfb, 0x45, 0xab, 0x6e, 0x53, 0x9d, 0x58, 0xf8, 0xfa, 0x2d, 0xf9, 0x52, 0xbc, 0x33, 0x89, 0x01, - 0x52, 0x49, 0xb1, 0xb9, 0xe2, 0x83, 0x7d, 0xd9, 0x0e, 0x94, 0xd1, 0x5e, 0x8b, 0x9b, 0xcf, 0xff, - 0x86, 0xe9, 0xca, 0xc1, 0x0b, 0xad, 0x2f, 0xe5, 0x3e, 0xd1, 0x04, 0xe9, 0x3e, 0xf2, 0x37, 0xdb, - 0xb0, 0x32, 0xfe, 0x6f, 0xe2, 0xdd, 0x23, 0x70, 0x93, 0xe9, 0x02, 0x96, 0x4a, 0xde, 0x21, 0x9a, - 0x95, 0xaa, 0x8f, 0xbd, 0xc7, 0x43, 0x65, 0xe4, 0xb9, 0xf8, 0xe0, 0x08, 0xdc, 0x08, 0xcc, 0x32, - 0xb2, 0x36, 0xd2, 0x89, 0x95, 0x77, 0xe9, 0x96, 0x08, 0xf1, 0x1e, 0xdf, 0x75, 0x20, 0xf1, 0x14, - 0x4d, 0xc0, 0x8d, 0x41, 0xcd, 0x7e, 0x4e, 0xe2, 0x2b, 0x72, 0x8a, 0x90, 0xce, 0x4d, 0x51, 0x80, - 0x95, 0xf1, 0x95, 0x78, 0xaf, 0x10, 0xce, 0x4c, 0xe4, 0x40, 0x32, 0x2d, 0x73, 0xc0, 0x3b, 0x7c, - 0xbb, 0x95, 0x2b, 0x2d, 0xfe, 0x10, 0xe2, 0xe9, 0x42, 0x25, 0x73, 0x78, 0x75, 0x95, 0x82, 0xa4, - 0x66, 0xb8, 0x92, 0x7d, 0xf8, 0xfd, 0x2d, 0x14, 0xee, 0xff, 0x18, 0x2e, 0x0c, 0xd8, 0xc5, 0xc4, - 0xa9, 0x96, 0xfe, 0x63, 0x80, 0xeb, 0x7f, 0xc8, 0xe1, 0xb5, 0x1e, 0xaf, 0x92, 0x17, 0xa0, 0x62, - 0xb7, 0x78, 0xba, 0x80, 0xe9, 0x25, 0xb9, 0xd6, 0x21, 0xc2, 0xad, 0x75, 0x9d, 0x2c, 0x8d, 0x52, - 0xf1, 0xf1, 0xf1, 0x3c, 0xd1, 0x06, 0x36, 0xf2, 0x73, 0x63, 0xb4, 0x91, 0x3d, 0x22, 0x42, 0x83, - 0xf2, 0x76, 0xf7, 0xba, 0xc1, 0xe1, 0xec, 0xc5, 0x5a, 0xcd, 0x8a, 0x3d, 0x42, 0xcf, 0x5e, 0x05, - 0xf0, 0xb3, 0x87, 0xb9, 0xd2, 0xe2, 0x4f, 0xf1, 0xe1, 0xc8, 0xc0, 0x45, 0x1c, 0xcd, 0x17, 0x7e, - 0x27, 0x52, 0x93, 0x52, 0x63, 0xbc, 0xd1, 0x41, 0x17, 0x14, 0x6f, 0x96, 0x61, 0x9a, 0xc6, 0x57, - 0x85, 0x0f, 0x95, 0x44, 0x48, 0xe7, 0x36, 0x4b, 0x80, 0xe1, 0x4c, 0x7e, 0xa9, 0xa7, 0x97, 0x79, - 0x75, 0xb5, 0x64, 0x26, 0x57, 0x32, 0x97, 0xc9, 0x98, 0xc2, 0x6b, 0x71, 0x9a, 0xc4, 0x55, 0x78, - 0xaa, 0x5b, 0x18, 0xe0, 0xd6, 0x22, 0xe4, 0x70, 0x82, 0x15, 0x85, 0xf2, 0x10, 0xdc, 0x74, 0x31, - 0xb4, 0xcf, 0xce, 0x15, 0x99, 0x60, 0x0d, 0x8a, 0x4b, 0x30, 0x02, 0x2e, 0x1d, 0xff, 0x11, 0x9f, - 0x86, 0xf2, 0x30, 0x8e, 0x47, 0x26, 0x5a, 0x5b, 0x79, 0x7f, 0x6b, 0x24, 0x8f, 0x7a, 0xef, 0x07, - 0xd7, 0x68, 0xd1, 0x3e, 0xe4, 0x61, 0x9a, 0x76, 0x18, 0xf2, 0x30, 0x4d, 0xbb, 0x0f, 0x39, 0x87, - 0xb1, 0xe3, 0x18, 0xd2, 0x38, 0x9a, 0x2a, 0x17, 0xe9, 0x24, 0x2b, 0x26, 0x2b, 0x4b, 0x3a, 0x36, - 0x28, 0xce, 0x91, 0x80, 0x71, 0xe6, 0x9c, 0x28, 0xeb, 0xc0, 0x14, 0x66, 0x54, 0xe6, 0x60, 0x80, - 0xcb, 0x9c, 0x90, 0xc3, 0x35, 0x70, 0xa3, 0x8c, 0xb4, 0x8d, 0xb2, 0x4e, 0x90, 0x35, 0x30, 0x44, - 0xb8, 0x1a, 0x58, 0x27, 0x71, 0xb9, 0x38, 0x53, 0x91, 0x3b, 0xd4, 0x95, 0x13, 0xd5, 0xbe, 0xc6, - 0x70, 0xe5, 0xa2, 0x81, 0x62, 0xaf, 0x89, 0xd3, 0x29, 0x9a, 0x5a, 0xd2, 0xab, 0xc6, 0x70, 0x5e, - 0x0d, 0x14, 0x6f, 0x84, 0x9a, 0x78, 0x12, 0x25, 0xd1, 0x72, 0xb5, 0x24, 0x37, 0x02, 0x8d, 0x72, - 0x1b, 0xa1, 0xad, 0x45, 0xd9, 0x81, 0xa5, 0xf8, 0x68, 0xe2, 0x94, 0x71, 0x78, 0xb4, 0xf4, 0x10, - 0x42, 0xc8, 0x9b, 0xf6, 0x3a, 0xb1, 0xa5, 0xdd, 0xbf, 0x3b, 0x62, 0xb7, 0x2e, 0x9f, 0x26, 0x2e, - 0x8a, 0x87, 0x17, 0x0e, 0x8c, 0xfc, 0xa1, 0x43, 0xb4, 0x0a, 0xf7, 0x7d, 0x78, 0x7c, 0xcd, 0x56, - 0xf8, 0x60, 0x38, 0x02, 0x4f, 0x59, 0xf2, 0x60, 0x40, 0x3a, 0x77, 0x30, 0x04, 0x18, 0x9e, 0xdc, - 0x5f, 0x51, 0x1f, 0xb2, 0xf2, 0x40, 0x4e, 0x6e, 0x1d, 0xe2, 0x26, 0xb7, 0xc9, 0xe2, 0x64, 0xc2, - 0x6a, 0x95, 0xe1, 0x64, 0x32, 0xd1, 0x28, 0x97, 0x4c, 0x6d, 0x2d, 0xf0, 0x78, 0xc7, 0x60, 0x61, - 0x6b, 0x32, 0xd5, 0x21, 0x6e, 0xbc, 0x4d, 0x16, 0x9f, 0xbb, 0xc7, 0x49, 0xe4, 0x36, 0x45, 0x83, - 0x3c, 0x77, 0x2b, 0x99, 0x3b, 0x77, 0x31, 0x55, 0x06, 0x7f, 0xb3, 0x23, 0x6e, 0x8f, 0x74, 0xba, - 0x8a, 0xf3, 0x5b, 0x5f, 0xaa, 0x0c, 0x24, 0xee, 0x27, 0xbd, 0x32, 0x89, 0x8a, 0x25, 0x35, 0x39, - 0x2d, 0xac, 0xf7, 0x7d, 0x78, 0x9d, 0x26, 0x38, 0x41, 0xb3, 0xce, 0x15, 0xc3, 0x97, 0x6d, 0x9d, - 0x2f, 0x74, 0x2e, 0x41, 0x03, 0x0c, 0x1f, 0x11, 0xcf, 0x60, 0xa9, 0x1d, 0x14, 0x73, 0x48, 0xb5, - 0xc4, 0x00, 0x77, 0x44, 0x84, 0x1c, 0xce, 0x89, 0xd3, 0x64, 0xa6, 0x03, 0x9b, 0x03, 0xf2, 0x6e, - 0x12, 0x42, 0x5c, 0x4e, 0x34, 0xd9, 0xd2, 0xce, 0x0a, 0x59, 0x0c, 0xf3, 0x4c, 0xd9, 0x91, 0xd1, - 0x19, 0x34, 0x93, 0xcc, 0xd1, 0x89, 0x30, 0x6f, 0xf9, 0x7d, 0x47, 0x1a, 0x7f, 0x50, 0x4e, 0xc0, - 0xe7, 0xe1, 0x1d, 0xfa, 0x13, 0x28, 0x1c, 0xd5, 0x1e, 0x0f, 0x95, 0x91, 0xd7, 0xe2, 0x93, 0xca, - 0x79, 0x0c, 0x36, 0xab, 0x6a, 0x30, 0x93, 0x7c, 0x0f, 0x4b, 0xce, 0xbb, 0xf5, 0xbb, 0xe2, 0xa5, - 0xef, 0x7f, 0x3b, 0xe2, 0xb3, 0xda, 0xd9, 0x31, 0x4c, 0x66, 0xd9, 0x27, 0xef, 0xe6, 0x2e, 0xf1, - 0x78, 0xfb, 0x59, 0x83, 0x79, 0xdf, 0x91, 0x1f, 0xaf, 0xdb, 0x0c, 0xdf, 0x34, 0x8a, 0x89, 0xf7, - 0x9b, 0xe1, 0x2e, 0xf9, 0x0d, 0x80, 0x11, 0xee, 0xa6, 0x51, 0x27, 0x4b, 0xa3, 0x5f, 0xc4, 0x8d, - 0x27, 0x6a, 0x7a, 0xb9, 0x4a, 0x25, 0xf5, 0x54, 0xb1, 0x91, 0x7c, 0xe0, 0xaf, 0x18, 0xc2, 0x07, - 0xbc, 0xbf, 0x23, 0x4d, 0x76, 0xf5, 0xb3, 0x4e, 0x1b, 0x38, 0x34, 0x7a, 0x59, 0x44, 0x6f, 0xa9, - 0x75, 0x21, 0xc5, 0x5f, 0xfd, 0x1a, 0x30, 0xf2, 0x7c, 0x2d, 0x6e, 0x4e, 0x62, 0xb5, 0x86, 0x62, - 0xbd, 0xc8, 0x07, 0x82, 0x4a, 0x67, 0x1f, 0x08, 0x30, 0x16, 0xa4, 0xbc, 0xd3, 0x69, 0x2e, 0xd2, - 0x29, 0xef, 0x55, 0x36, 0xe5, 0x2b, 0x28, 0xbc, 0x91, 0x14, 0x7f, 0xfb, 0xcb, 0xd0, 0x01, 0xd7, - 0xb6, 0x76, 0x0d, 0xea, 0x75, 0x62, 0xf1, 0x21, 0x92, 0xdf, 0x15, 0x36, 0x23, 0xd9, 0x6b, 0xbb, - 0x4a, 0x04, 0x43, 0xd9, 0xdf, 0x42, 0x95, 0xc1, 0xaf, 0xc4, 0xad, 0xea, 0x7f, 0x74, 0xcf, 0xe9, - 0xb3, 0x01, 0x9a, 0x37, 0x9c, 0x41, 0x67, 0xbe, 0xfe, 0xc8, 0x95, 0xe9, 0xb6, 0xf5, 0x91, 0x2b, - 0x57, 0xb7, 0x3d, 0x72, 0x15, 0x10, 0x8e, 0x9c, 0x9d, 0x26, 0xed, 0x4b, 0x5f, 0xaa, 0x5c, 0x64, - 0x04, 0x05, 0x4b, 0x9f, 0xfd, 0x85, 0x4b, 0xf7, 0x41, 0x5b, 0x4a, 0x12, 0x85, 0xbb, 0xd7, 0x89, - 0xc5, 0x9f, 0x64, 0x5e, 0xad, 0x4a, 0x2b, 0x17, 0xa3, 0x51, 0x58, 0xef, 0x75, 0x83, 0xbd, 0xe3, - 0x93, 0x47, 0xbf, 0x3f, 0x58, 0x47, 0x0e, 0xac, 0xed, 0x47, 0x7a, 0xb0, 0xf9, 0x35, 0x98, 0xeb, - 0xc1, 0xda, 0x0d, 0xf2, 0x47, 0xda, 0x01, 0xf5, 0xa4, 0x7b, 0x7e, 0x23, 0xd7, 0x1e, 0xfd, 0x1f, - 0x00, 0x00, 0xff, 0xff, 0x6e, 0x16, 0x3b, 0x7d, 0x0d, 0x16, 0x00, 0x00, + // 1134 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0x6d, 0x6f, 0x23, 0x35, + 0x10, 0xc7, 0xa9, 0x04, 0x27, 0xe1, 0xe3, 0xd1, 0x9c, 0x38, 0xa9, 0x48, 0x70, 0x70, 0x2d, 0x1c, + 0xcd, 0x91, 0xdc, 0x03, 0xc7, 0xfb, 0xdc, 0x43, 0x7b, 0x45, 0x57, 0x11, 0x92, 0x6b, 0x8b, 0x40, + 0x3a, 0xc9, 0x4d, 0xa6, 0xc9, 0xd2, 0xcd, 0x7a, 0xb1, 0x9d, 0x88, 0xbe, 0x42, 0xe2, 0x2d, 0x12, + 0x9f, 0x8d, 0x8f, 0x84, 0xf6, 0xc1, 0xde, 0xf1, 0xee, 0xac, 0xb3, 0x79, 0x17, 0xe5, 0xff, 0xf3, + 0x8c, 0x3d, 0x1e, 0x8f, 0x67, 0xcd, 0x76, 0x8d, 0xb8, 0x88, 0xc1, 0x2c, 0x45, 0x22, 0xe6, 0xa0, + 0x34, 0xa8, 0x75, 0x34, 0x85, 0x7e, 0xaa, 0xa4, 0x91, 0xfc, 0x16, 0xa5, 0xed, 0xde, 0xf6, 0xfe, + 0x9d, 0x09, 0x23, 0x0a, 0xfc, 0xd1, 0x7f, 0x3d, 0xf6, 0xfe, 0xeb, 0x5c, 0x3b, 0x29, 0x34, 0x7e, + 0xcc, 0xde, 0x1e, 0x45, 0xc9, 0x9c, 0x7f, 0xde, 0x6f, 0x8e, 0xc9, 0x84, 0x31, 0xfc, 0xb1, 0x02, + 0x6d, 0x76, 0xbf, 0x68, 0xd5, 0x75, 0x2a, 0x13, 0x0d, 0x5f, 0xbd, 0xc5, 0x5f, 0xb1, 0x77, 0x26, + 0x31, 0x40, 0xca, 0x29, 0x36, 0x57, 0xac, 0xb1, 0x3b, 0xed, 0x80, 0xb3, 0xf6, 0x86, 0xdd, 0x7c, + 0xf1, 0x27, 0x4c, 0x57, 0x06, 0x5e, 0x4a, 0x79, 0xc5, 0xf7, 0x89, 0x21, 0x48, 0xb7, 0x96, 0xbf, + 0xde, 0x84, 0x39, 0xfb, 0xbf, 0xb0, 0x77, 0x8f, 0xc0, 0x4c, 0xa6, 0x0b, 0x58, 0x0a, 0x7e, 0x97, + 0x18, 0xe6, 0x54, 0x6b, 0x7b, 0x2f, 0x0c, 0x39, 0xcb, 0x73, 0xf6, 0xc1, 0x11, 0x98, 0x11, 0xa8, + 0x65, 0xa4, 0x75, 0x24, 0x13, 0xcd, 0xef, 0xd1, 0x23, 0x11, 0x62, 0x7d, 0x7c, 0xdb, 0x81, 0xc4, + 0x21, 0x9a, 0x80, 0x19, 0x83, 0x98, 0xfd, 0x94, 0xc4, 0xd7, 0x64, 0x88, 0x90, 0x1e, 0x0a, 0x91, + 0x87, 0x39, 0xfb, 0x82, 0xbd, 0x57, 0x0a, 0xe7, 0x2a, 0x32, 0xc0, 0x03, 0x23, 0x73, 0xc0, 0x7a, + 0xf8, 0x66, 0x23, 0xe7, 0x5c, 0xfc, 0xc6, 0xd8, 0xb3, 0x85, 0x48, 0xe6, 0xf0, 0xfa, 0x3a, 0x05, + 0x4e, 0x45, 0xb8, 0x92, 0xad, 0xf9, 0xfd, 0x0d, 0x14, 0x9e, 0xff, 0x18, 0x2e, 0x15, 0xe8, 0xc5, + 0xc4, 0x88, 0x96, 0xf9, 0x63, 0x20, 0x34, 0x7f, 0x9f, 0xc3, 0x7b, 0x3d, 0x5e, 0x25, 0x2f, 0x41, + 0xc4, 0x66, 0xf1, 0x6c, 0x01, 0xd3, 0x2b, 0x72, 0xaf, 0x7d, 0x24, 0xb4, 0xd7, 0x75, 0xd2, 0x39, + 0x4a, 0xd9, 0xc7, 0xc7, 0xf3, 0x44, 0x2a, 0x28, 0xe4, 0x17, 0x4a, 0x49, 0xc5, 0x7b, 0x84, 0x85, + 0x06, 0x65, 0xdd, 0xdd, 0xef, 0x06, 0xfb, 0xd1, 0x8b, 0xa5, 0x98, 0x95, 0x67, 0x84, 0x8e, 0x5e, + 0x05, 0x84, 0xa3, 0x87, 0x39, 0xe7, 0xe2, 0x77, 0xf6, 0xe1, 0x48, 0xc1, 0x65, 0x1c, 0xcd, 0x17, + 0xf6, 0x24, 0x52, 0x41, 0xa9, 0x31, 0xd6, 0xd1, 0x41, 0x17, 0x14, 0x1f, 0x96, 0x61, 0x9a, 0xc6, + 0xd7, 0xa5, 0x1f, 0x2a, 0x89, 0x90, 0x1e, 0x3a, 0x2c, 0x1e, 0x86, 0x33, 0xf9, 0x95, 0x9c, 0x5e, + 0xe5, 0xd5, 0x55, 0x93, 0x99, 0x5c, 0xc9, 0xa1, 0x4c, 0xc6, 0x14, 0xde, 0x8b, 0xd3, 0x24, 0xae, + 0xcc, 0x53, 0xd3, 0xc2, 0x40, 0x68, 0x2f, 0x7c, 0x0e, 0x27, 0x58, 0x59, 0x28, 0x0f, 0xc1, 0x4c, + 0x17, 0x43, 0xfd, 0xfc, 0x42, 0x90, 0x09, 0xd6, 0xa0, 0x42, 0x09, 0x46, 0xc0, 0xce, 0xe3, 0x5f, + 0xec, 0x53, 0x5f, 0x1e, 0xc6, 0xf1, 0x48, 0x45, 0x6b, 0xcd, 0x1f, 0x6c, 0xb4, 0x64, 0x51, 0xeb, + 0xfb, 0xe1, 0x16, 0x23, 0xda, 0x97, 0x3c, 0x4c, 0xd3, 0x0e, 0x4b, 0x1e, 0xa6, 0x69, 0xf7, 0x25, + 0xe7, 0x30, 0xf6, 0x38, 0x86, 0x34, 0x8e, 0xa6, 0xc2, 0x44, 0x32, 0xc9, 0x8a, 0xc9, 0x4a, 0x93, + 0x1e, 0x1b, 0x54, 0xc8, 0x23, 0x01, 0xe3, 0xcc, 0x39, 0x11, 0xda, 0x80, 0x2a, 0x9d, 0x51, 0x99, + 0x83, 0x81, 0x50, 0xe6, 0xf8, 0x1c, 0xae, 0x81, 0x85, 0x32, 0x92, 0x3a, 0xca, 0x26, 0x41, 0xd6, + 0x40, 0x1f, 0x09, 0xd5, 0xc0, 0x3a, 0x89, 0xcb, 0xc5, 0xb9, 0x88, 0xcc, 0xa1, 0xac, 0x3c, 0x51, + 0xe3, 0x6b, 0x4c, 0xa8, 0x5c, 0x34, 0x50, 0xec, 0x6b, 0x62, 0x64, 0x8a, 0x42, 0x4b, 0xfa, 0xaa, + 0x31, 0x21, 0x5f, 0x0d, 0x14, 0x1f, 0x84, 0x9a, 0x78, 0x12, 0x25, 0xd1, 0x72, 0xb5, 0x24, 0x0f, + 0x02, 0x8d, 0x86, 0x0e, 0x42, 0xdb, 0x08, 0x37, 0x81, 0x25, 0xfb, 0x68, 0x62, 0x84, 0x32, 0x78, + 0xb5, 0xf4, 0x12, 0x7c, 0xc8, 0x3a, 0xed, 0x75, 0x62, 0x9d, 0xbb, 0x7f, 0x76, 0xd8, 0x6e, 0x5d, + 0x3e, 0x4d, 0x4c, 0x14, 0x0f, 0x2f, 0x0d, 0x28, 0xfe, 0x7d, 0x07, 0x6b, 0x15, 0x6e, 0xe7, 0xf0, + 0x64, 0xcb, 0x51, 0xf8, 0x62, 0x38, 0x02, 0x4b, 0x69, 0xf2, 0x62, 0x40, 0x7a, 0xe8, 0x62, 0xf0, + 0x30, 0x1c, 0xdc, 0x33, 0x34, 0x87, 0xac, 0x3c, 0x90, 0xc1, 0xad, 0x43, 0xa1, 0xe0, 0x36, 0x59, + 0x9c, 0x4c, 0x58, 0xad, 0x32, 0x9c, 0x4c, 0x26, 0x1a, 0x0d, 0x25, 0x53, 0xdb, 0x08, 0xbc, 0xde, + 0x31, 0x68, 0xd8, 0x98, 0x4c, 0x75, 0x28, 0xb4, 0xde, 0x26, 0x8b, 0xef, 0xdd, 0xe3, 0x24, 0x32, + 0x45, 0xd1, 0x20, 0xef, 0xdd, 0x4a, 0x0e, 0xdd, 0xbb, 0x98, 0x72, 0xc6, 0xff, 0xde, 0x61, 0xb7, + 0x47, 0x32, 0x5d, 0xc5, 0x79, 0xd7, 0x97, 0x0a, 0x05, 0x89, 0xf9, 0x51, 0xae, 0x54, 0x22, 0x62, + 0x4e, 0x05, 0xa7, 0x85, 0xb5, 0x7e, 0x1f, 0x6d, 0x33, 0x04, 0x27, 0x68, 0x36, 0xb9, 0x72, 0xf9, + 0xbc, 0x6d, 0xf2, 0xa5, 0x1e, 0x4a, 0x50, 0x0f, 0xc3, 0x57, 0xc4, 0x73, 0x58, 0x4a, 0x03, 0x65, + 0x0c, 0xa9, 0x91, 0x18, 0x08, 0x5d, 0x11, 0x3e, 0x87, 0x73, 0xe2, 0x34, 0x99, 0x49, 0xcf, 0xcd, + 0x01, 0xd9, 0x9b, 0xf8, 0x50, 0x28, 0x27, 0x9a, 0xac, 0x73, 0xa7, 0x19, 0x2f, 0x97, 0x79, 0x2e, + 0xf4, 0x48, 0xc9, 0x0c, 0x9a, 0xf1, 0xc0, 0xd5, 0x89, 0x30, 0xeb, 0xf2, 0xbb, 0x8e, 0x34, 0xfe, + 0xa0, 0x9c, 0x80, 0xcd, 0xc3, 0xbb, 0xf4, 0x27, 0x90, 0xbf, 0xaa, 0xbd, 0x30, 0xe4, 0x2c, 0xaf, + 0xd9, 0x27, 0x95, 0xe7, 0x31, 0xe8, 0xac, 0xaa, 0xc1, 0x8c, 0x87, 0x67, 0xe8, 0x38, 0xeb, 0xad, + 0xdf, 0x15, 0x77, 0x7e, 0xff, 0xdd, 0x61, 0x9f, 0xd5, 0xee, 0x8e, 0x61, 0x32, 0xcb, 0x3e, 0x79, + 0x8b, 0x5e, 0xe2, 0xc9, 0xe6, 0xbb, 0x06, 0xf3, 0x76, 0x22, 0x3f, 0x6c, 0x3b, 0x0c, 0x77, 0x1a, + 0x65, 0xe0, 0xed, 0x61, 0xb8, 0x47, 0x7e, 0x03, 0x60, 0x24, 0xd4, 0x69, 0xd4, 0x49, 0xe7, 0xe8, + 0x67, 0x76, 0xe3, 0xa9, 0x98, 0x5e, 0xad, 0x52, 0x4e, 0x3d, 0x55, 0x14, 0x92, 0x35, 0xfc, 0x65, + 0x80, 0xb0, 0x06, 0x1f, 0xec, 0x70, 0x95, 0xb5, 0x7e, 0xda, 0x48, 0x05, 0x87, 0x4a, 0x2e, 0x4b, + 0xeb, 0x2d, 0xb5, 0xce, 0xa7, 0xc2, 0xad, 0x5f, 0x03, 0x46, 0x3e, 0xdf, 0xb0, 0x9b, 0x93, 0x58, + 0xac, 0xa1, 0xdc, 0x2f, 0xf2, 0x81, 0xa0, 0xd2, 0x83, 0x0f, 0x04, 0x18, 0xf3, 0x52, 0xde, 0xc8, + 0x34, 0x17, 0xe9, 0x94, 0xb7, 0x6a, 0x30, 0xe5, 0x2b, 0xc8, 0xef, 0x48, 0xca, 0xbf, 0x6d, 0x33, + 0x74, 0x10, 0x1a, 0x5b, 0x6b, 0x83, 0x7a, 0x9d, 0x58, 0x7c, 0x89, 0xe4, 0xbd, 0x42, 0xb1, 0x92, + 0xbd, 0xb6, 0x56, 0xc2, 0x5b, 0xca, 0xfe, 0x06, 0xca, 0x19, 0xbf, 0x66, 0xb7, 0xaa, 0xff, 0x51, + 0x9f, 0xd3, 0x0f, 0x1a, 0x68, 0x76, 0x38, 0x83, 0xce, 0x7c, 0xfd, 0x91, 0x2b, 0xd3, 0x75, 0xeb, + 0x23, 0x57, 0xae, 0x6e, 0x7a, 0xe4, 0x2a, 0x21, 0x6c, 0x39, 0xbb, 0x4d, 0xda, 0xb7, 0xde, 0xa9, + 0x21, 0xcb, 0x08, 0xf2, 0xb6, 0x3e, 0xfb, 0x0b, 0x97, 0xee, 0x83, 0xb6, 0x94, 0x24, 0x0a, 0x77, + 0xaf, 0x13, 0x8b, 0x3f, 0xc9, 0xac, 0x5a, 0x95, 0xd6, 0x90, 0x8d, 0x46, 0x61, 0xbd, 0xdf, 0x0d, + 0xc6, 0xef, 0xa4, 0x67, 0x79, 0x17, 0x48, 0xbd, 0x93, 0x9e, 0xe1, 0xd6, 0xef, 0x4e, 0x3b, 0x60, + 0xad, 0x3d, 0x7d, 0xfc, 0xeb, 0xc3, 0x75, 0x64, 0x40, 0xeb, 0x7e, 0x24, 0x07, 0xc5, 0xaf, 0xc1, + 0x5c, 0x0e, 0xd6, 0x66, 0x90, 0x3f, 0xf9, 0x0e, 0xa8, 0x07, 0xe2, 0x8b, 0x1b, 0xb9, 0xf6, 0xf8, + 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x3f, 0xf9, 0x7a, 0x5b, 0x16, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -207,6 +208,8 @@ type TabletManagerClient interface { SlaveWasPromoted(ctx context.Context, in *tabletmanagerdata.SlaveWasPromotedRequest, opts ...grpc.CallOption) (*tabletmanagerdata.SlaveWasPromotedResponse, error) // Deprecated SlaveWasRestarted(ctx context.Context, in *tabletmanagerdata.SlaveWasRestartedRequest, opts ...grpc.CallOption) (*tabletmanagerdata.SlaveWasRestartedResponse, error) + // Generic VExec request. Can be used for various purposes + VExec(ctx context.Context, in *tabletmanagerdata.VExecRequest, opts ...grpc.CallOption) (*tabletmanagerdata.VExecResponse, error) } type tabletManagerClient struct { @@ -731,6 +734,15 @@ func (c *tabletManagerClient) SlaveWasRestarted(ctx context.Context, in *tabletm return out, nil } +func (c *tabletManagerClient) VExec(ctx context.Context, in *tabletmanagerdata.VExecRequest, opts ...grpc.CallOption) (*tabletmanagerdata.VExecResponse, error) { + out := new(tabletmanagerdata.VExecResponse) + err := c.cc.Invoke(ctx, "/tabletmanagerservice.TabletManager/VExec", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // TabletManagerServer is the server API for TabletManager service. type TabletManagerServer interface { // Ping returns the input payload @@ -826,6 +838,8 @@ type TabletManagerServer interface { SlaveWasPromoted(context.Context, *tabletmanagerdata.SlaveWasPromotedRequest) (*tabletmanagerdata.SlaveWasPromotedResponse, error) // Deprecated SlaveWasRestarted(context.Context, *tabletmanagerdata.SlaveWasRestartedRequest) (*tabletmanagerdata.SlaveWasRestartedResponse, error) + // Generic VExec request. Can be used for various purposes + VExec(context.Context, *tabletmanagerdata.VExecRequest) (*tabletmanagerdata.VExecResponse, error) } // UnimplementedTabletManagerServer can be embedded to have forward compatible implementations. @@ -988,6 +1002,9 @@ func (*UnimplementedTabletManagerServer) SlaveWasPromoted(ctx context.Context, r func (*UnimplementedTabletManagerServer) SlaveWasRestarted(ctx context.Context, req *tabletmanagerdata.SlaveWasRestartedRequest) (*tabletmanagerdata.SlaveWasRestartedResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SlaveWasRestarted not implemented") } +func (*UnimplementedTabletManagerServer) VExec(ctx context.Context, req *tabletmanagerdata.VExecRequest) (*tabletmanagerdata.VExecResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VExec not implemented") +} func RegisterTabletManagerServer(s *grpc.Server, srv TabletManagerServer) { s.RegisterService(&_TabletManager_serviceDesc, srv) @@ -1935,6 +1952,24 @@ func _TabletManager_SlaveWasRestarted_Handler(srv interface{}, ctx context.Conte return interceptor(ctx, in, info, handler) } +func _TabletManager_VExec_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(tabletmanagerdata.VExecRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TabletManagerServer).VExec(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/tabletmanagerservice.TabletManager/VExec", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TabletManagerServer).VExec(ctx, req.(*tabletmanagerdata.VExecRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _TabletManager_serviceDesc = grpc.ServiceDesc{ ServiceName: "tabletmanagerservice.TabletManager", HandlerType: (*TabletManagerServer)(nil), @@ -2139,6 +2174,10 @@ var _TabletManager_serviceDesc = grpc.ServiceDesc{ MethodName: "SlaveWasRestarted", Handler: _TabletManager_SlaveWasRestarted_Handler, }, + { + MethodName: "VExec", + Handler: _TabletManager_VExec_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/go/vt/schema/online_ddl.go b/go/vt/schema/online_ddl.go new file mode 100644 index 00000000000..c5151f866c6 --- /dev/null +++ b/go/vt/schema/online_ddl.go @@ -0,0 +1,190 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "context" + "encoding/json" + "fmt" + "regexp" + "strings" + "time" + + "github.com/google/uuid" + + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" +) + +var ( + migrationBasePath = "schema-migration" + onlineDdlUUIDRegexp = regexp.MustCompile(`^[0-f]{8}_[0-f]{4}_[0-f]{4}_[0-f]{4}_[0-f]{12}$`) +) + +// MigrationBasePath is the root for all schema migration entries +func MigrationBasePath() string { + return migrationBasePath +} + +// MigrationRequestsPath is the base path for all newly received schema migration requests. +// such requests need to be investigates/reviewed, and to be assigned to all shards +func MigrationRequestsPath() string { + return fmt.Sprintf("%s/requests", MigrationBasePath()) +} + +// MigrationQueuedPath is the base path for schema migrations that have been reviewed and +// queued for execution. Kept for historical reference +func MigrationQueuedPath() string { + return fmt.Sprintf("%s/queued", MigrationBasePath()) +} + +// MigrationJobsKeyspacePath is the base path for a tablet job, by keyspace +func MigrationJobsKeyspacePath(keyspace string) string { + return fmt.Sprintf("%s/jobs/%s", MigrationBasePath(), keyspace) +} + +// MigrationJobsKeyspaceShardPath is the base path for a tablet job, by keyspace and shard +func MigrationJobsKeyspaceShardPath(keyspace, shard string) string { + return fmt.Sprintf("%s/%s", MigrationJobsKeyspacePath(keyspace), shard) +} + +// OnlineDDLStatus is an indicator to a online DDL status +type OnlineDDLStatus string + +const ( + OnlineDDLStatusRequested OnlineDDLStatus = "requested" + OnlineDDLStatusCancelled OnlineDDLStatus = "cancelled" + OnlineDDLStatusQueued OnlineDDLStatus = "queued" + OnlineDDLStatusReady OnlineDDLStatus = "ready" + OnlineDDLStatusRunning OnlineDDLStatus = "running" + OnlineDDLStatusComplete OnlineDDLStatus = "complete" + OnlineDDLStatusFailed OnlineDDLStatus = "failed" +) + +const ( + // DDLStrategyNormal means not an online-ddl migration. Just a normal MySQL ALTER TABLE + DDLStrategyNormal sqlparser.DDLStrategy = "" + // DDLStrategyGhost requests gh-ost to run the migration + DDLStrategyGhost sqlparser.DDLStrategy = "gh-ost" + // DDLStrategyPTOSC requests pt-online-schema-change to run the migration + DDLStrategyPTOSC sqlparser.DDLStrategy = "pt-osc" +) + +// OnlineDDL encapsulates the relevant information in an online schema change request +type OnlineDDL struct { + Keyspace string `json:"keyspace,omitempty"` + Table string `json:"table,omitempty"` + Schema string `json:"schema,omitempty"` + SQL string `json:"sql,omitempty"` + UUID string `json:"uuid,omitempty"` + Strategy sqlparser.DDLStrategy `json:"strategy,omitempty"` + Options string `json:"options,omitempty"` + RequestTime int64 `json:"time_created,omitempty"` + Status OnlineDDLStatus `json:"status,omitempty"` +} + +// FromJSON creates an OnlineDDL from json +func FromJSON(bytes []byte) (*OnlineDDL, error) { + onlineDDL := &OnlineDDL{} + err := json.Unmarshal(bytes, onlineDDL) + return onlineDDL, err +} + +// ReadTopo reads a OnlineDDL object from given topo connection +func ReadTopo(ctx context.Context, conn topo.Conn, entryPath string) (*OnlineDDL, error) { + bytes, _, err := conn.Get(ctx, entryPath) + if err != nil { + return nil, fmt.Errorf("ReadTopo Get %s error: %s", entryPath, err.Error()) + } + onlineDDL, err := FromJSON(bytes) + if err != nil { + return nil, fmt.Errorf("ReadTopo unmarshal %s error: %s", entryPath, err.Error()) + } + return onlineDDL, nil +} + +// NewOnlineDDL creates a schema change request with self generated UUID and RequestTime +func NewOnlineDDL(keyspace string, table string, sql string, strategy sqlparser.DDLStrategy, options string) (*OnlineDDL, error) { + u, err := CreateUUID() + if err != nil { + return nil, err + } + return &OnlineDDL{ + Keyspace: keyspace, + Table: table, + SQL: sql, + UUID: u, + Strategy: strategy, + Options: options, + RequestTime: time.Now().UnixNano(), + Status: OnlineDDLStatusRequested, + }, nil +} + +// RequestTimeSeconds converts request time to seconds (losing nano precision) +func (onlineDDL *OnlineDDL) RequestTimeSeconds() int64 { + return onlineDDL.RequestTime / int64(time.Second) +} + +// JobsKeyspaceShardPath returns job/// +func (onlineDDL *OnlineDDL) JobsKeyspaceShardPath(shard string) string { + return MigrationJobsKeyspaceShardPath(onlineDDL.Keyspace, shard) +} + +// ToJSON exports this onlineDDL to JSON +func (onlineDDL *OnlineDDL) ToJSON() ([]byte, error) { + return json.Marshal(onlineDDL) +} + +// ToString returns a simple string representation of this instance +func (onlineDDL *OnlineDDL) ToString() string { + return fmt.Sprintf("OnlineDDL: keyspace=%s, table=%s, sql=%s", onlineDDL.Keyspace, onlineDDL.Table, onlineDDL.SQL) +} + +// WriteTopo writes this online DDL to given topo connection, based on basePath and and this DDL's UUID +func (onlineDDL *OnlineDDL) WriteTopo(ctx context.Context, conn topo.Conn, basePath string) error { + if onlineDDL.UUID == "" { + return fmt.Errorf("onlineDDL UUID not found; keyspace=%s, sql=%s", onlineDDL.Keyspace, onlineDDL.SQL) + } + bytes, err := onlineDDL.ToJSON() + if err != nil { + return fmt.Errorf("onlineDDL marshall error:%s, keyspace=%s, sql=%s", err.Error(), onlineDDL.Keyspace, onlineDDL.SQL) + } + _, err = conn.Create(ctx, fmt.Sprintf("%s/%s", basePath, onlineDDL.UUID), bytes) + if err != nil { + return fmt.Errorf("onlineDDL topo create error:%s, keyspace=%s, sql=%s", err.Error(), onlineDDL.Keyspace, onlineDDL.SQL) + } + return nil +} + +// CreateUUID creates a globally unique ID, returned as string +// example result: 55d00cdc_e6ab_11ea_bfe6_0242ac1c000d +func CreateUUID() (string, error) { + u, err := uuid.NewUUID() + if err != nil { + return "", err + } + result := u.String() + result = strings.Replace(result, "-", "_", -1) + return result, nil +} + +// IsOnlineDDLUUID answers 'true' when the given string is an online-ddl UUID, e.g.: +// a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9a +func IsOnlineDDLUUID(uuid string) bool { + return onlineDdlUUIDRegexp.MatchString(uuid) +} diff --git a/go/vt/schema/online_ddl_test.go b/go/vt/schema/online_ddl_test.go new file mode 100644 index 00000000000..4475fcc632c --- /dev/null +++ b/go/vt/schema/online_ddl_test.go @@ -0,0 +1,46 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateUUID(t *testing.T) { + _, err := CreateUUID() + assert.NoError(t, err) +} + +func TestIsOnlineDDLUUID(t *testing.T) { + for i := 0; i < 20; i++ { + uuid, err := CreateUUID() + assert.NoError(t, err) + assert.True(t, IsOnlineDDLUUID(uuid)) + } + tt := []string{ + "a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9a_", + "_a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9a", + "a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9z", + "a0638f6b-ec7b-11ea-9bf8-000d3a9b8a9a", + "a0638f6b_ec7b_11ea_9bf8_000d3a9b8a9", + } + for _, tc := range tt { + assert.False(t, IsOnlineDDLUUID(tc)) + } +} diff --git a/go/vt/schema/parser.go b/go/vt/schema/parser.go new file mode 100644 index 00000000000..da09fb8cabf --- /dev/null +++ b/go/vt/schema/parser.go @@ -0,0 +1,87 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "fmt" + "regexp" + "strings" +) + +var ( + // ALTER TABLE + // ALTER WITH_GHOST TABLE + // ALTER WITH_GHOST LAG_'--max-lag-millis=2.5 --throttle-http=...' TABLE + // ALTER WITH_PT TABLE + alterTableBasicPattern = `(?s)(?i)\balter\s+(with\s+|\s+|).*?table\s+` + alterTableExplicitSchemaTableRegexps = []*regexp.Regexp{ + // ALTER TABLE `scm`.`tbl` something + // ALTER WITH_GHOST TABLE `scm`.`tbl` something + // ALTER WITH_PT TABLE `scm`.`tbl` something + regexp.MustCompile(alterTableBasicPattern + "`" + `([^` + "`" + `]+)` + "`" + `[.]` + "`" + `([^` + "`" + `]+)` + "`" + `\s+(.*$)`), + // ALTER TABLE `scm`.tbl something + regexp.MustCompile(alterTableBasicPattern + "`" + `([^` + "`" + `]+)` + "`" + `[.]([\S]+)\s+(.*$)`), + // ALTER TABLE scm.`tbl` something + regexp.MustCompile(alterTableBasicPattern + `([\S]+)[.]` + "`" + `([^` + "`" + `]+)` + "`" + `\s+(.*$)`), + // ALTER TABLE scm.tbl something + regexp.MustCompile(alterTableBasicPattern + `([\S]+)[.]([\S]+)\s+(.*$)`), + } + alterTableExplicitTableRegexps = []*regexp.Regexp{ + // ALTER TABLE `tbl` something + regexp.MustCompile(alterTableBasicPattern + "`" + `([^` + "`" + `]+)` + "`" + `\s+(.*$)`), + // ALTER TABLE tbl something + regexp.MustCompile(alterTableBasicPattern + `([\S]+)\s+(.*$)`), + } +) + +// ParseAlterTableOptions parses a ALTER ... TABLE... statement into: +// - explicit schema and table, if available +// - alter options (anything that follows ALTER ... TABLE) +func ParseAlterTableOptions(alterStatement string) (explicitSchema, explicitTable, alterOptions string) { + alterOptions = strings.TrimSpace(alterStatement) + for _, alterTableRegexp := range alterTableExplicitSchemaTableRegexps { + if submatch := alterTableRegexp.FindStringSubmatch(alterOptions); len(submatch) > 0 { + explicitSchema = submatch[2] + explicitTable = submatch[3] + alterOptions = submatch[4] + return explicitSchema, explicitTable, alterOptions + } + } + for _, alterTableRegexp := range alterTableExplicitTableRegexps { + if submatch := alterTableRegexp.FindStringSubmatch(alterOptions); len(submatch) > 0 { + explicitTable = submatch[2] + alterOptions = submatch[3] + return explicitSchema, explicitTable, alterOptions + } + } + return explicitSchema, explicitTable, alterOptions +} + +// RemoveOnlineDDLHints removes a WITH_GHOST or WITH_PT hint, which is vitess-specific, +// from an ALTER TABLE statement +// e.g "ALTER WITH 'gh-ost' TABLE my_table DROP COLUMN i" -> "ALTER TABLE `my_table` DROP COLUMN i" +func RemoveOnlineDDLHints(alterStatement string) (normalizedAlterStatement string) { + explicitSchema, explicitTable, alterOptions := ParseAlterTableOptions(alterStatement) + + if explicitTable == "" { + return alterOptions + } + if explicitSchema == "" { + return fmt.Sprintf("ALTER TABLE `%s` %s", explicitTable, alterOptions) + } + return fmt.Sprintf("ALTER TABLE `%s`.`%s` %s", explicitSchema, explicitTable, alterOptions) +} diff --git a/go/vt/schema/parser_test.go b/go/vt/schema/parser_test.go new file mode 100644 index 00000000000..c24ffe82f9f --- /dev/null +++ b/go/vt/schema/parser_test.go @@ -0,0 +1,88 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "testing" +) + +func TestParseAlterTableOptions(t *testing.T) { + type expect struct { + schema, table, options string + } + tests := map[string]expect{ + "add column i int, drop column d": {schema: "", table: "", options: "add column i int, drop column d"}, + " add column i int, drop column d ": {schema: "", table: "", options: "add column i int, drop column d"}, + "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table t add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table `t` add column i int, drop column d": {schema: "", table: "t", options: "add column i int, drop column d"}, + "alter table `scm`.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table `scm`.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter with 'gh-ost' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + " alter with 'gh-ost' table scm.`t` add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter with 'pt-osc' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter with 'gh-ost' '--some-option=5 --another-option=false' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter with 'gh-ost' '--initially-drop-old-table' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "alter with 'gh-ost' '--initially-drop-old-table --execute' table scm.t add column i int, drop column d": {schema: "scm", table: "t", options: "add column i int, drop column d"}, + "ALTER WITH 'gh-ost' TABLE scm.t ADD COLUMN i int, DROP COLUMN d": {schema: "scm", table: "t", options: "ADD COLUMN i int, DROP COLUMN d"}, + } + for query, expect := range tests { + schema, table, options := ParseAlterTableOptions(query) + if schema != expect.schema { + t.Errorf("schema: %+v, want:%+v", schema, expect.schema) + } + if table != expect.table { + t.Errorf("table: %+v, want:%+v", table, expect.table) + } + if options != expect.options { + t.Errorf("options: %+v, want:%+v", options, expect.options) + } + } +} + +func TestRemoveOnlineDDLHints(t *testing.T) { + tests := map[string]string{ + "ALTER TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", + " ALTER TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", + "ALTER WITH 'gh-ost' TABLE my_table DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", + "ALTER WITH 'pt-osc' TABLE `my_table` DROP COLUMN i": "ALTER TABLE `my_table` DROP COLUMN i", + "ALTER WITH 'pt-osc' TABLE scm.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", + "ALTER WITH 'pt-osc' TABLE `scm`.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", + "ALTER WITH 'gh-ost' TABLE `scm`.`my_table` DROP COLUMN i": "ALTER TABLE `scm`.`my_table` DROP COLUMN i", + ` + ALTER WITH 'gh-ost' + TABLE scm.my_table + DROP COLUMN i + `: "ALTER TABLE `scm`.`my_table` DROP COLUMN i", + ` + ALTER + WITH + 'gh-ost' + TABLE scm.my_table DROP COLUMN i, + ADD j INT + `: "ALTER TABLE `scm`.`my_table` DROP COLUMN i," + ` + ADD j INT`, + } + for query, expect := range tests { + normalizedQuery := RemoveOnlineDDLHints(query) + if normalizedQuery != expect { + t.Errorf("got: %+v, want:%+v", normalizedQuery, expect) + } + } +} diff --git a/go/vt/schema/tablegc.go b/go/vt/schema/tablegc.go new file mode 100644 index 00000000000..ecc6bf5a63e --- /dev/null +++ b/go/vt/schema/tablegc.go @@ -0,0 +1,130 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "fmt" + "regexp" + "strings" + "time" + + "github.com/google/uuid" + + "vitess.io/vitess/go/textutil" +) + +// TableGCState provides a state for the type of GC table: HOLD? PURGE? EVAC? DROP? See details below +type TableGCState string + +const ( + // HoldTableGCState is the state where table was just renamed away. Data is still in tact, + // and the user has the option to rename it back. A "safety" period. + HoldTableGCState TableGCState = "HOLD" + // PurgeTableGCState is the state where we purge table data. Table in this state is "lost" to the user. + // if in this state, the table will be fully purged. + PurgeTableGCState TableGCState = "PURGE" + // EvacTableGCState is a waiting state, where we merely wait out the table's pages to be + // gone from InnoDB's buffer pool, adaptive hash index cache, and whatnot. + EvacTableGCState TableGCState = "EVAC" + // DropTableGCState is the state where the table is to be dropped. Probably ASAP + DropTableGCState TableGCState = "DROP" +) + +const ( + readableTimeFormat = "20060102150405" +) + +var ( + gcTableNameRegexp = regexp.MustCompile(`^_vt_(HOLD|PURGE|EVAC|DROP)_[0-f]{32}_([0-9]{14})$`) + + gcStates = map[string]TableGCState{ + string(HoldTableGCState): HoldTableGCState, + string(PurgeTableGCState): PurgeTableGCState, + string(EvacTableGCState): EvacTableGCState, + string(DropTableGCState): DropTableGCState, + } +) + +// CreateUUID creates a globally unique ID, returned as non-delimited string +// example result: 55d00cdce6ab11eabfe60242ac1c000d +func createUUID() (string, error) { + u, err := uuid.NewUUID() + if err != nil { + return "", err + } + result := u.String() + result = strings.Replace(result, "-", "", -1) + return result, nil +} + +// ToReadableTimestamp returns a timestamp, in seconds resolution, that is human readable +// (as opposed to unix timestamp which is just a number) +// Example: for Aug 25 2020, 16:04:25 we return "20200825160425" +func ToReadableTimestamp(t time.Time) string { + return t.Format(readableTimeFormat) +} + +func generateGCTableName(state TableGCState, t time.Time) (string, error) { + uuid, err := createUUID() + if err != nil { + return "", err + } + timestamp := ToReadableTimestamp(t) + return fmt.Sprintf("_vt_%s_%s_%s", state, uuid, timestamp), nil +} + +// AnalyzeGCTableName analyzes a given table name to see if it's a GC table, and if so, parse out +// its state and timestamp +func AnalyzeGCTableName(tableName string) (isGCTable bool, state TableGCState, t time.Time, err error) { + submatch := gcTableNameRegexp.FindStringSubmatch(tableName) + if len(submatch) == 0 { + return false, state, t, nil + } + t, err = time.Parse(readableTimeFormat, submatch[2]) + return true, TableGCState(submatch[1]), t, err +} + +// IsGCTableName answers 'true' when the given table name stands for a GC table +func IsGCTableName(tableName string) bool { + return gcTableNameRegexp.MatchString(tableName) +} + +// GenerateRenameStatement generates a "RENAME TABLE" statement, where a table is renamed to a GC table. +func GenerateRenameStatement(fromTableName string, state TableGCState, t time.Time) (statement string, toTableName string, err error) { + toTableName, err = generateGCTableName(state, t) + if err != nil { + return "", "", err + } + return fmt.Sprintf("RENAME TABLE `%s` TO %s", fromTableName, toTableName), toTableName, nil +} + +// ParseGCLifecycle parses a comma separated list of gc states and returns a map of indicated states +func ParseGCLifecycle(gcLifecycle string) (states map[TableGCState]bool, err error) { + states = make(map[TableGCState]bool) + tokens := textutil.SplitDelimitedList(gcLifecycle) + for _, token := range tokens { + token = strings.ToUpper(token) + state, ok := gcStates[token] + if !ok { + return states, fmt.Errorf("Unknown GC state: %s", token) + } + states[state] = true + } + // DROP is implicitly included. + states[DropTableGCState] = true + return states, nil +} diff --git a/go/vt/schema/tablegc_test.go b/go/vt/schema/tablegc_test.go new file mode 100644 index 00000000000..f7e74ab4a3b --- /dev/null +++ b/go/vt/schema/tablegc_test.go @@ -0,0 +1,151 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package schema + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestIsGCTableName(t *testing.T) { + tm := time.Now() + states := []TableGCState{HoldTableGCState, PurgeTableGCState, EvacTableGCState, DropTableGCState} + for _, state := range states { + for i := 0; i < 10; i++ { + tableName, err := generateGCTableName(state, tm) + assert.NoError(t, err) + assert.True(t, IsGCTableName(tableName)) + } + } + names := []string{ + "_vt_DROP_6ace8bcef73211ea87e9f875a4d24e90_202009151204100", + "_vt_DROP_6ace8bcef73211ea87e9f875a4d24e90_20200915120410 ", + "__vt_DROP_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + "_vt_DROP_6ace8bcef73211ea87e9f875a4d2_20200915120410", + "_vt_DROP_6ace8bcef73211ea87e9f875a4d24e90_20200915", + "_vt_OTHER_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + "_vt_OTHER_6ace8bcef73211ea87e9f875a4d24e90_zz20200915120410", + } + for _, tableName := range names { + assert.False(t, IsGCTableName(tableName)) + } +} + +func TestAnalyzeGCTableName(t *testing.T) { + baseTime, err := time.Parse(time.RFC1123, "Tue, 15 Sep 2020 12:04:10 UTC") + assert.NoError(t, err) + tt := []struct { + tableName string + state TableGCState + t time.Time + }{ + { + tableName: "_vt_DROP_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + state: DropTableGCState, + t: baseTime, + }, + { + tableName: "_vt_HOLD_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + state: HoldTableGCState, + t: baseTime, + }, + { + tableName: "_vt_EVAC_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + state: EvacTableGCState, + t: baseTime, + }, + { + tableName: "_vt_PURGE_6ace8bcef73211ea87e9f875a4d24e90_20200915120410", + state: PurgeTableGCState, + t: baseTime, + }, + } + for _, ts := range tt { + isGC, state, tm, err := AnalyzeGCTableName(ts.tableName) + assert.NoError(t, err) + assert.True(t, isGC) + assert.Equal(t, ts.state, state) + assert.Equal(t, ts.t, tm) + } +} + +func TestParseGCLifecycle(t *testing.T) { + tt := []struct { + lifecycle string + states map[TableGCState]bool + expectErr bool + }{ + { + lifecycle: "", + states: map[TableGCState]bool{ + DropTableGCState: true, + }, + }, + { + lifecycle: "drop", + states: map[TableGCState]bool{ + DropTableGCState: true, + }, + }, + { + lifecycle: " drop, ", + states: map[TableGCState]bool{ + DropTableGCState: true, + }, + }, + { + lifecycle: "hold, drop", + states: map[TableGCState]bool{ + HoldTableGCState: true, + DropTableGCState: true, + }, + }, + { + lifecycle: "hold,purge, evac;drop", + states: map[TableGCState]bool{ + HoldTableGCState: true, + PurgeTableGCState: true, + EvacTableGCState: true, + DropTableGCState: true, + }, + }, + { + lifecycle: "hold,purge,evac,drop", + states: map[TableGCState]bool{ + HoldTableGCState: true, + PurgeTableGCState: true, + EvacTableGCState: true, + DropTableGCState: true, + }, + }, + { + lifecycle: "hold, other, drop", + expectErr: true, + }, + } + for _, ts := range tt { + states, err := ParseGCLifecycle(ts.lifecycle) + if ts.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, ts.states, states) + } + } +} diff --git a/go/vt/schemamanager/tablet_executor.go b/go/vt/schemamanager/tablet_executor.go index a563fe54275..1f933967fa2 100644 --- a/go/vt/schemamanager/tablet_executor.go +++ b/go/vt/schemamanager/tablet_executor.go @@ -24,7 +24,9 @@ import ( "golang.org/x/net/context" "vitess.io/vitess/go/sync2" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/wrangler" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -160,6 +162,13 @@ func (exec *TabletExecutor) detectBigSchemaChanges(ctx context.Context, parsedDD switch ddl.Action { case sqlparser.DropDDLAction, sqlparser.CreateDDLAction, sqlparser.TruncateDDLAction, sqlparser.RenameDDLAction: continue + case sqlparser.AlterDDLAction: + if ddl.OnlineHint != nil { + if ddl.OnlineHint.Strategy != schema.DDLStrategyNormal { + // Seeing that we intend to run an online-schema-change, we can skip the "big change" check. + continue + } + } } tableName := ddl.Table.Name.String() if rowCount, ok := tableWithCount[tableName]; ok { @@ -209,15 +218,46 @@ func (exec *TabletExecutor) Execute(ctx context.Context, sqls []string) *Execute } }() + // We added the WITH_GHOST and WITH_PT hints to ALTER TABLE syntax, but these hints are + // obviously not accepted by MySQL. + // To run preflightSchemaChanges we must clean up such hints from the ALTER TABLE statement. + // Because our sqlparser does not do a complete parse of ALTER TABLE statements at this time, + // we resort to temporary regexp based parsing. + // TODO(shlomi): replace the below with sqlparser based reconstruction of the query, + // when sqlparser has a complete coverage of ALTER TABLE syntax + sqlsWithoutAlterTableHints := []string{} + for _, sql := range sqls { + sqlsWithoutAlterTableHints = append(sqlsWithoutAlterTableHints, schema.RemoveOnlineDDLHints(sql)) + } // Make sure the schema changes introduce a table definition change. - if err := exec.preflightSchemaChanges(ctx, sqls); err != nil { + if err := exec.preflightSchemaChanges(ctx, sqlsWithoutAlterTableHints); err != nil { execResult.ExecutorErr = err.Error() return &execResult } for index, sql := range sqls { execResult.CurSQLIndex = index - exec.executeOnAllTablets(ctx, &execResult, sql) + + stat, err := sqlparser.Parse(sql) + if err != nil { + execResult.ExecutorErr = err.Error() + return &execResult + } + strategy := schema.DDLStrategyNormal + options := "" + tableName := "" + switch ddl := stat.(type) { + case *sqlparser.DDL: + if ddl.Action == sqlparser.AlterDDLAction { + if ddl.OnlineHint != nil { + strategy = ddl.OnlineHint.Strategy + options = ddl.OnlineHint.Options + } + } + tableName = ddl.Table.Name.String() + } + exec.wr.Logger().Infof("Received DDL request. strategy = %+v", strategy) + exec.executeOnAllTablets(ctx, &execResult, sql, tableName, strategy, options) if len(execResult.FailedShards) > 0 { break } @@ -225,7 +265,30 @@ func (exec *TabletExecutor) Execute(ctx context.Context, sqls []string) *Execute return &execResult } -func (exec *TabletExecutor) executeOnAllTablets(ctx context.Context, execResult *ExecuteResult, sql string) { +func (exec *TabletExecutor) executeOnAllTablets( + ctx context.Context, execResult *ExecuteResult, sql string, + tableName string, strategy sqlparser.DDLStrategy, options string, +) { + if strategy != schema.DDLStrategyNormal { + onlineDDL, err := schema.NewOnlineDDL(exec.keyspace, tableName, sql, strategy, options) + if err != nil { + execResult.ExecutorErr = err.Error() + return + } + conn, err := exec.wr.TopoServer().ConnForCell(ctx, topo.GlobalCell) + if err != nil { + execResult.ExecutorErr = fmt.Sprintf("online DDL ConnForCell error:%s", err.Error()) + return + } + err = onlineDDL.WriteTopo(ctx, conn, schema.MigrationRequestsPath()) + if err != nil { + execResult.ExecutorErr = err.Error() + } + exec.wr.Logger().Infof("UUID=%+v", onlineDDL.UUID) + exec.wr.Logger().Printf("%s\n", onlineDDL.UUID) + return + } + var wg sync.WaitGroup numOfMasterTablets := len(exec.tablets) wg.Add(numOfMasterTablets) diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index c8ac040f9d7..9434e4b6b9c 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -264,6 +264,17 @@ func IsVschemaDDL(ddl *DDL) bool { return false } +// IsOnlineSchemaDDL returns true if the query is an online schema change DDL +func IsOnlineSchemaDDL(ddl *DDL, sql string) bool { + switch ddl.Action { + case AlterDDLAction: + if ddl.OnlineHint != nil { + return ddl.OnlineHint.Strategy != "" + } + } + return false +} + // SplitAndExpression breaks up the Expr into AND-separated conditions // and appends them to filters. Outer parenthesis are removed. Precedence // should be taken into account if expressions are recombined. diff --git a/go/vt/sqlparser/ast.go b/go/vt/sqlparser/ast.go index ecdeddad73c..ef7e5c2fe61 100644 --- a/go/vt/sqlparser/ast.go +++ b/go/vt/sqlparser/ast.go @@ -197,6 +197,14 @@ type ( Charset string } + // DDLStrategy suggests how an ALTER TABLE should run (e.g. "" for normal, "gh-ost" or "pt-osc") + DDLStrategy string + + // OnlineDDLHint indicates strategy and options for running an online DDL + OnlineDDLHint struct { + Strategy DDLStrategy + Options string + } // DBDDLAction is an enum for DBDDL Actions DBDDLAction int8 @@ -218,6 +226,7 @@ type ( TableSpec *TableSpec OptLike *OptLike PartitionSpec *PartitionSpec + OnlineHint *OnlineDDLHint // VindexSpec is set for CreateVindexDDLAction, DropVindexDDLAction, AddColVindexDDLAction, DropColVindexDDLAction. VindexSpec *VindexSpec diff --git a/go/vt/sqlparser/constants.go b/go/vt/sqlparser/constants.go index 657e42b3073..bf3d9edc596 100644 --- a/go/vt/sqlparser/constants.go +++ b/go/vt/sqlparser/constants.go @@ -64,6 +64,9 @@ const ( AddSequenceStr = "add sequence" AddAutoIncStr = "add auto_increment" + // Online DDL hint + OnlineStr = "online" + // Vindex DDL param to specify the owner of a vindex VindexOwnerStr = "owner" diff --git a/go/vt/sqlparser/normalizer_test.go b/go/vt/sqlparser/normalizer_test.go index bfd6003a966..c28d3c61ba5 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -38,6 +38,16 @@ func TestNormalize(t *testing.T) { outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.BytesBindVariable([]byte("aa")), }, + }, { + // placeholder + in: "select * from t where col=?", + outstmt: "select * from t where col = :v1", + outbv: map[string]*querypb.BindVariable{}, + }, { + // qualified table name + in: "select * from `t` where col=?", + outstmt: "select * from t where col = :v1", + outbv: map[string]*querypb.BindVariable{}, }, { // str val in select in: "select 'aa' from t", @@ -202,6 +212,15 @@ func TestNormalize(t *testing.T) { outbv: map[string]*querypb.BindVariable{ "bv1": sqltypes.StringBindVariable("test"), }, + }, { + // insert syntax + in: "insert into a (v1, v2, v3) values (1, '2', 3)", + outstmt: "insert into a(v1, v2, v3) values (:bv1, :bv2, :bv3)", + outbv: map[string]*querypb.BindVariable{ + "bv1": sqltypes.Int64BindVariable(1), + "bv2": sqltypes.StringBindVariable("2"), + "bv3": sqltypes.Int64BindVariable(3), + }, }} for _, tc := range testcases { stmt, err := Parse(tc.in) diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index e65c3beb9c4..0d1010ce278 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -890,9 +890,6 @@ var ( input: "set @variable = 42", }, { input: "set @period.variable = 42", - }, { - input: "alter ignore table a add foo", - output: "alter table a", }, { input: "alter table a add foo", output: "alter table a", diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index 0f0c9fb27a6..4b7162b410f 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -91,6 +91,7 @@ type yySymType struct { colKeyOpt ColumnKeyOption optVal Expr LengthScaleOption LengthScaleOption + OnlineDDLHint *OnlineDDLHint columnDefinition *ColumnDefinition indexDefinition *IndexDefinition indexInfo *IndexInfo @@ -867,37 +868,37 @@ var yyExca = [...]int{ 39, 372, -2, 380, -1, 400, - 121, 703, - -2, 699, + 121, 706, + -2, 702, -1, 401, - 121, 704, - -2, 700, + 121, 707, + -2, 703, -1, 415, 39, 373, -2, 385, -1, 416, 39, 374, -2, 386, - -1, 435, - 89, 958, - -2, 74, -1, 436, - 89, 873, + 89, 961, + -2, 74, + -1, 437, + 89, 876, -2, 75, - -1, 441, - 89, 840, + -1, 442, + 89, 843, -2, 665, - -1, 443, - 89, 905, + -1, 444, + 89, 908, -2, 667, - -1, 943, - 121, 706, - -2, 702, - -1, 1028, + -1, 946, + 121, 709, + -2, 705, + -1, 1031, 57, 56, 59, 56, -2, 60, - -1, 1377, + -1, 1380, 5, 624, 18, 624, 20, 624, @@ -908,1029 +909,800 @@ var yyExca = [...]int{ const yyPrivate = 57344 -const yyLast = 17396 +const yyLast = 17911 var yyAct = [...]int{ - 400, 1621, 1419, 1578, 1303, 1205, 1050, 1357, 1611, 359, - 1225, 1493, 1022, 1393, 344, 695, 1527, 1358, 1206, 373, - 1354, 1093, 1254, 734, 1049, 1369, 1192, 71, 3, 596, - 330, 1480, 741, 1059, 1322, 1363, 930, 440, 1143, 92, - 865, 1280, 1001, 290, 937, 313, 290, 1019, 779, 1271, - 885, 92, 1063, 290, 772, 1024, 1008, 417, 402, 739, - 762, 69, 963, 761, 1089, 907, 744, 28, 1030, 346, - 776, 1046, 769, 778, 335, 565, 67, 605, 708, 342, - 92, 893, 66, 566, 290, 331, 290, 751, 334, 585, - 1079, 8, 7, 6, 1614, 1598, 1609, 1586, 1606, 30, - 31, 32, 60, 34, 35, 1420, 1597, 1585, 1339, 1449, - 374, 29, 570, 1387, 1242, 615, 1112, 1241, 408, 64, - 1243, 780, 72, 781, 36, 55, 56, 1040, 58, 333, - 1111, 286, 282, 283, 284, 403, 94, 95, 96, 332, - 29, 423, 427, 709, 1388, 1389, 628, 45, 1041, 1042, - 434, 59, 1262, 1072, 74, 75, 76, 77, 78, 79, - 1483, 94, 95, 96, 30, 1080, 1440, 60, 34, 35, - 339, 623, 1110, 1438, 1305, 624, 621, 622, 404, 323, - 892, 1553, 657, 656, 666, 667, 659, 660, 661, 662, - 663, 664, 665, 658, 325, 437, 668, 385, 321, 391, - 392, 389, 390, 388, 387, 386, 626, 602, 627, 604, - 94, 95, 96, 393, 394, 854, 59, 38, 39, 41, - 40, 43, 940, 57, 853, 1107, 1104, 1105, 278, 1103, - 1306, 276, 1307, 280, 894, 895, 896, 616, 617, 851, - 1605, 601, 603, 1608, 1629, 1571, 44, 63, 62, 1579, - 1302, 53, 54, 42, 1064, 1323, 855, 1002, 611, 285, - 852, 1528, 1114, 1117, 586, 1625, 572, 46, 47, 280, - 48, 49, 50, 51, 1308, 1066, 1530, 290, 577, 578, - 1536, 858, 290, 1290, 587, 631, 842, 1299, 290, 1226, - 1228, 1560, 1380, 1301, 290, 594, 1325, 1379, 600, 1378, - 568, 575, 1109, 293, 281, 92, 1124, 92, 1073, 1123, - 680, 681, 582, 1462, 92, 1286, 1287, 1288, 1386, 1197, - 1172, 1151, 1036, 755, 1108, 1047, 92, 92, 613, 693, - 279, 592, 1584, 1327, 599, 1331, 1162, 1326, 1159, 1324, - 658, 668, 629, 668, 1329, 1238, 980, 1529, 648, 886, - 880, 1080, 82, 1328, 645, 637, 277, 610, 606, 1569, - 61, 598, 1554, 642, 643, 1545, 1330, 1332, 1113, 612, - 648, 1227, 1066, 1367, 588, 589, 590, 607, 608, 1065, - 579, 1623, 580, 1115, 1624, 581, 1622, 1289, 782, 1537, - 1535, 83, 1294, 1291, 1282, 1292, 1285, 1300, 1281, 1298, - 641, 1341, 1283, 1284, 94, 95, 96, 94, 95, 96, - 964, 678, 1169, 964, 844, 614, 1293, 614, 1260, 640, - 638, 639, 1574, 748, 614, 61, 92, 571, 1589, 290, - 290, 290, 732, 92, 1069, 731, 887, 881, 29, 92, - 1630, 1070, 696, 1489, 1488, 597, 680, 681, 680, 681, - 1275, 677, 679, 659, 660, 661, 662, 663, 664, 665, - 658, 1406, 777, 668, 914, 711, 713, 715, 717, 719, - 721, 722, 1136, 1137, 1138, 745, 1065, 760, 912, 913, - 911, 1274, 692, 1263, 1631, 1591, 697, 698, 699, 700, - 701, 702, 703, 704, 1570, 707, 710, 710, 710, 716, - 710, 710, 716, 710, 724, 725, 726, 727, 728, 729, - 730, 1506, 1066, 1486, 412, 29, 573, 574, 682, 683, - 684, 685, 686, 687, 688, 689, 690, 691, 733, 59, - 712, 714, 1272, 718, 720, 878, 723, 94, 95, 96, - 766, 910, 432, 870, 94, 95, 96, 1032, 437, 657, - 656, 666, 667, 659, 660, 661, 662, 663, 664, 665, - 658, 275, 1366, 668, 1542, 290, 1446, 647, 645, 840, - 92, 1158, 843, 564, 845, 290, 290, 92, 92, 92, - 646, 647, 645, 290, 648, 1541, 290, 1402, 1343, 290, - 863, 864, 1033, 290, 1035, 92, 1533, 1607, 648, 1067, - 92, 92, 92, 290, 92, 92, 1144, 661, 662, 663, - 664, 665, 658, 1593, 412, 668, 1065, 92, 92, 985, - 986, 1062, 1060, 994, 1061, 869, 646, 647, 645, 1458, - 867, 1058, 1064, 1533, 1582, 618, 68, 743, 428, 429, - 430, 644, 630, 1157, 648, 1156, 657, 656, 666, 667, - 659, 660, 661, 662, 663, 664, 665, 658, 859, 1544, - 668, 902, 904, 905, 646, 647, 645, 1193, 903, 931, - 993, 908, 646, 647, 645, 94, 95, 96, 933, 982, - 614, 1410, 648, 1533, 412, 1533, 1561, 614, 614, 614, - 648, 412, 92, 656, 666, 667, 659, 660, 661, 662, - 663, 664, 665, 658, 889, 614, 668, 1533, 1532, 968, - 614, 614, 614, 1005, 614, 614, 952, 955, 1232, 981, - 1031, 909, 965, 1478, 1477, 92, 92, 614, 614, 947, - 1004, 943, 1464, 412, 942, 1461, 412, 70, 646, 647, - 645, 1412, 1411, 92, 646, 647, 645, 696, 1408, 1409, - 290, 1408, 1407, 92, 993, 412, 648, 290, 1005, 290, - 934, 935, 648, 1005, 412, 644, 412, 290, 290, 290, - 1005, 944, 973, 974, 1193, 92, 789, 788, 92, 1246, - 993, 411, 362, 361, 364, 365, 366, 367, 1039, 92, - 566, 363, 368, 943, 1020, 405, 999, 94, 95, 96, - 1175, 932, 59, 995, 94, 95, 96, 1174, 1245, 941, - 666, 667, 659, 660, 661, 662, 663, 664, 665, 658, - 1366, 906, 668, 1032, 915, 916, 917, 918, 919, 920, - 921, 922, 923, 924, 925, 926, 927, 928, 929, 1034, - 997, 1029, 993, 290, 92, 1037, 92, 59, 1116, 1038, - 977, 1031, 290, 290, 290, 290, 290, 983, 290, 290, - 987, 1095, 290, 92, 1355, 1054, 30, 1366, 1033, 857, - 1031, 941, 1010, 1013, 1014, 1015, 1011, 1021, 1012, 1016, - 290, 969, 1370, 1371, 774, 290, 30, 290, 290, 1599, - 437, 290, 92, 437, 1081, 1082, 1083, 1513, 841, 1495, - 1074, 1091, 1092, 1469, 1051, 848, 849, 850, 1094, 1398, - 1370, 1371, 1376, 1249, 1090, 1131, 1085, 412, 59, 1084, - 948, 949, 1304, 868, 954, 957, 958, 1496, 872, 873, - 874, 908, 876, 877, 1097, 1616, 1375, 401, 59, 1612, - 1400, 1373, 1355, 1276, 30, 882, 883, 890, 861, 972, - 1217, 1214, 975, 976, 614, 1218, 614, 657, 656, 666, - 667, 659, 660, 661, 662, 663, 664, 665, 658, 1200, - 1213, 668, 1603, 614, 1215, 1201, 93, 1139, 1182, 1216, - 291, 909, 1219, 291, 1014, 1015, 1596, 1347, 93, 742, - 291, 1601, 1191, 1190, 1267, 290, 59, 787, 595, 960, - 1259, 1181, 735, 1152, 1576, 1575, 290, 290, 290, 290, - 290, 1186, 403, 961, 736, 1511, 1257, 93, 290, 1207, - 1251, 291, 290, 291, 1456, 1168, 290, 1198, 1491, 1202, - 1100, 290, 290, 860, 1018, 290, 290, 290, 406, 407, - 409, 1455, 1195, 1185, 410, 70, 1189, 1454, 1244, 1224, - 92, 1350, 1150, 1196, 1188, 404, 1247, 1193, 625, 1250, - 1194, 1618, 1617, 1255, 1255, 1163, 1153, 1209, 1210, 1208, - 1212, 1231, 1211, 1220, 867, 1160, 884, 756, 1233, 418, - 749, 1230, 1235, 1140, 1141, 1142, 1256, 1618, 1239, 1558, - 1236, 1484, 979, 419, 405, 73, 68, 65, 92, 92, - 746, 747, 421, 1, 420, 766, 312, 1075, 1076, 1077, - 1078, 1610, 1203, 1204, 1252, 1253, 766, 766, 766, 766, - 766, 1421, 1492, 1086, 1087, 1088, 1106, 1577, 92, 1526, - 1392, 1057, 1021, 1279, 1229, 1273, 1010, 1013, 1014, 1015, - 1011, 766, 1012, 1016, 1048, 766, 1295, 81, 563, 80, - 1568, 1266, 92, 1268, 1269, 1270, 879, 609, 931, 1056, - 1055, 1148, 1149, 1534, 1261, 1051, 1264, 1265, 1071, 1482, - 1399, 1258, 1099, 1573, 1101, 795, 793, 1321, 794, 1312, - 1310, 1311, 1166, 792, 797, 1320, 796, 791, 290, 305, - 891, 1128, 322, 1334, 1333, 1318, 1017, 783, 92, 1340, - 1096, 750, 84, 1297, 92, 92, 1356, 1296, 1102, 614, - 943, 1068, 302, 942, 291, 1207, 619, 620, 307, 291, - 676, 1359, 1187, 1240, 438, 291, 431, 1361, 984, 738, - 92, 291, 1365, 290, 1453, 1349, 1167, 1374, 614, 705, - 962, 765, 93, 345, 93, 901, 360, 92, 357, 92, - 92, 93, 358, 1255, 1255, 1391, 988, 1199, 1382, 650, - 1384, 343, 1385, 93, 93, 1381, 425, 1319, 1405, 418, - 337, 1390, 764, 757, 1009, 1396, 1397, 290, 1007, 1006, - 1383, 770, 1372, 419, 1395, 1368, 763, 992, 1344, 414, - 415, 416, 421, 959, 420, 1552, 1448, 290, 413, 371, - 52, 33, 327, 92, 633, 1422, 92, 92, 92, 290, - 422, 1414, 1360, 1319, 29, 1314, 1315, 1353, 23, 22, - 21, 20, 19, 25, 18, 336, 1415, 17, 1417, 16, - 1335, 1336, 583, 1337, 1338, 37, 1403, 1404, 91, 27, - 1427, 1428, 26, 766, 15, 1345, 1346, 14, 13, 1436, - 324, 12, 11, 10, 9, 5, 4, 636, 24, 694, - 2, 0, 1051, 93, 1051, 0, 291, 291, 291, 0, - 93, 0, 0, 0, 0, 0, 93, 1457, 0, 439, - 0, 1207, 0, 0, 0, 1466, 0, 0, 0, 0, - 0, 92, 0, 0, 0, 0, 0, 1247, 1465, 92, - 0, 0, 0, 0, 945, 946, 0, 0, 0, 0, - 1476, 0, 0, 0, 92, 1475, 0, 0, 0, 0, - 0, 92, 0, 0, 0, 0, 0, 1278, 0, 0, - 1401, 0, 0, 0, 0, 1499, 0, 0, 0, 1431, - 0, 0, 978, 0, 0, 0, 0, 0, 0, 0, - 1447, 0, 0, 0, 0, 1497, 1309, 0, 0, 0, - 0, 0, 92, 92, 0, 92, 0, 0, 0, 0, - 92, 1510, 92, 92, 92, 290, 1512, 0, 1359, 92, - 0, 0, 0, 0, 1429, 0, 0, 1524, 1514, 1471, - 1472, 1473, 1531, 0, 1538, 0, 92, 290, 1485, 0, - 1487, 1519, 291, 1520, 1522, 1523, 1051, 93, 0, 0, - 0, 0, 291, 291, 93, 93, 93, 0, 0, 0, - 291, 1559, 0, 291, 614, 1498, 291, 1546, 0, 1567, - 291, 0, 93, 1359, 92, 1565, 1494, 93, 93, 93, - 291, 93, 93, 1566, 0, 92, 92, 0, 0, 0, - 0, 0, 1581, 0, 93, 93, 1580, 1539, 0, 1540, - 0, 92, 0, 0, 1587, 0, 0, 1505, 0, 1360, - 0, 29, 290, 1207, 0, 0, 0, 0, 0, 0, - 92, 0, 0, 0, 1518, 0, 0, 1595, 0, 0, - 0, 0, 0, 0, 1525, 0, 0, 1600, 1602, 0, - 92, 0, 1543, 0, 439, 649, 439, 0, 0, 0, - 0, 0, 0, 439, 1500, 1501, 1502, 1503, 1504, 1615, - 1626, 0, 1507, 1508, 1360, 632, 634, 0, 0, 93, - 0, 1604, 1433, 1434, 0, 1435, 0, 0, 1437, 0, - 1439, 336, 0, 1146, 0, 0, 0, 1147, 0, 0, - 706, 0, 0, 0, 0, 0, 0, 0, 1154, 1155, - 1494, 1051, 93, 93, 1161, 0, 0, 1164, 1165, 0, - 0, 0, 0, 0, 0, 1171, 737, 740, 0, 1173, - 93, 0, 1176, 1177, 1178, 1179, 1180, 291, 0, 0, - 93, 0, 0, 0, 291, 0, 291, 0, 0, 0, - 0, 0, 0, 1479, 291, 291, 291, 0, 0, 0, - 0, 0, 93, 0, 0, 93, 0, 0, 0, 1613, - 0, 1445, 0, 0, 0, 753, 93, 0, 0, 1222, - 1223, 0, 439, 0, 0, 652, 0, 655, 784, 0, - 0, 0, 1490, 669, 670, 671, 672, 673, 674, 675, - 0, 653, 654, 651, 657, 656, 666, 667, 659, 660, - 661, 662, 663, 664, 665, 658, 0, 0, 668, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 291, 93, 0, 93, 1619, 0, 0, 0, 0, 291, - 291, 291, 291, 291, 1452, 291, 291, 0, 0, 291, - 93, 657, 656, 666, 667, 659, 660, 661, 662, 663, - 664, 665, 658, 0, 0, 668, 0, 291, 0, 0, - 0, 0, 291, 0, 291, 291, 0, 0, 291, 93, - 0, 0, 0, 0, 0, 657, 656, 666, 667, 659, - 660, 661, 662, 663, 664, 665, 658, 0, 0, 668, - 0, 0, 0, 0, 0, 0, 0, 0, 1316, 1317, - 0, 0, 0, 0, 0, 871, 0, 0, 0, 439, - 0, 0, 0, 0, 0, 0, 439, 439, 439, 657, - 656, 666, 667, 659, 660, 661, 662, 663, 664, 665, - 658, 0, 888, 668, 439, 0, 0, 0, 0, 439, - 439, 439, 0, 439, 439, 0, 0, 0, 0, 0, - 0, 897, 898, 899, 900, 0, 439, 439, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 0, - 0, 0, 291, 0, 1377, 0, 0, 0, 0, 0, + 400, 1614, 1624, 1422, 1581, 1306, 1053, 1228, 344, 1496, + 1208, 1360, 373, 1530, 1483, 359, 1209, 1025, 743, 1396, + 697, 1062, 1361, 1049, 1082, 1357, 1195, 1096, 1257, 408, + 1022, 1052, 71, 3, 1366, 441, 736, 617, 330, 92, + 598, 1325, 868, 290, 1372, 313, 290, 69, 933, 1066, + 1146, 92, 769, 290, 1274, 1283, 940, 774, 1011, 1004, + 1027, 764, 888, 741, 763, 966, 746, 402, 781, 346, + 417, 28, 910, 780, 1033, 566, 1092, 67, 753, 335, + 92, 771, 778, 567, 290, 615, 290, 607, 72, 711, + 66, 896, 342, 331, 8, 288, 334, 7, 587, 6, + 278, 1617, 1601, 276, 1612, 326, 1589, 1609, 710, 1423, + 1600, 1588, 1342, 1115, 1452, 571, 1390, 438, 1391, 1392, + 74, 75, 76, 77, 78, 79, 630, 1114, 1044, 1045, + 94, 95, 96, 782, 333, 783, 568, 1043, 570, 403, + 30, 423, 427, 60, 34, 35, 332, 385, 1265, 391, + 392, 389, 390, 388, 387, 386, 1075, 1308, 94, 95, + 96, 1486, 435, 393, 394, 286, 282, 283, 284, 1113, + 1556, 659, 658, 668, 669, 661, 662, 663, 664, 665, + 666, 667, 660, 1083, 1245, 670, 1443, 1244, 629, 1076, + 1246, 625, 59, 1441, 323, 626, 623, 624, 94, 95, + 96, 604, 279, 606, 971, 895, 325, 321, 628, 856, + 618, 619, 855, 1309, 1310, 853, 1611, 1608, 1582, 1305, + 429, 1005, 1110, 1107, 1108, 1574, 1106, 1067, 277, 1632, + 588, 1628, 1539, 1326, 1311, 603, 605, 1531, 613, 573, + 861, 633, 844, 943, 897, 898, 899, 1383, 854, 280, + 857, 1069, 1533, 1229, 1231, 1382, 1381, 569, 1069, 1117, + 1120, 659, 658, 668, 669, 661, 662, 663, 664, 665, + 666, 667, 660, 576, 1328, 670, 411, 290, 578, 579, + 293, 1302, 290, 281, 589, 1165, 1127, 1304, 290, 1126, + 94, 95, 96, 285, 290, 596, 583, 1563, 602, 1112, + 682, 683, 1162, 1465, 1389, 92, 1200, 92, 1175, 1154, + 1039, 1330, 757, 1334, 92, 1329, 695, 1327, 1147, 594, + 1050, 1111, 1332, 1532, 1069, 670, 92, 92, 601, 577, + 660, 1331, 1241, 670, 586, 1230, 1587, 612, 983, 1083, + 593, 1540, 1538, 889, 1333, 1335, 595, 1626, 883, 614, + 1627, 1557, 1625, 631, 600, 1068, 94, 95, 96, 917, + 639, 814, 1068, 1161, 580, 1116, 581, 1065, 1063, 582, + 1064, 644, 645, 915, 916, 914, 608, 1061, 1067, 650, + 1118, 649, 647, 590, 591, 592, 1572, 609, 610, 988, + 989, 1303, 620, 1301, 1548, 682, 683, 1370, 650, 632, + 82, 61, 663, 664, 665, 666, 667, 660, 412, 784, + 670, 680, 682, 683, 94, 95, 96, 647, 648, 649, + 647, 733, 642, 643, 967, 640, 92, 641, 1068, 290, + 890, 290, 290, 650, 92, 884, 650, 734, 599, 83, + 92, 846, 648, 649, 647, 802, 698, 1344, 659, 658, + 668, 669, 661, 662, 663, 664, 665, 666, 667, 660, + 650, 762, 670, 1263, 1577, 648, 649, 647, 1409, 750, + 1160, 438, 1159, 1449, 1592, 1633, 714, 716, 59, 720, + 722, 761, 725, 650, 773, 967, 815, 1172, 747, 779, + 913, 648, 649, 647, 735, 713, 715, 717, 719, 721, + 723, 724, 1492, 905, 907, 908, 1139, 1140, 1141, 650, + 906, 1594, 828, 831, 832, 833, 834, 835, 836, 1634, + 837, 838, 839, 840, 841, 816, 817, 818, 819, 800, + 801, 829, 428, 803, 572, 804, 805, 806, 807, 808, + 809, 810, 811, 812, 813, 820, 821, 822, 823, 824, + 825, 826, 827, 659, 658, 668, 669, 661, 662, 663, + 664, 665, 666, 667, 660, 1072, 290, 670, 1491, 433, + 842, 92, 1073, 845, 1278, 847, 290, 290, 92, 92, + 92, 648, 649, 647, 290, 94, 95, 96, 290, 1346, + 1573, 290, 866, 867, 1277, 290, 1266, 92, 1509, 650, + 1489, 985, 92, 92, 92, 290, 92, 92, 830, 1275, + 430, 431, 94, 95, 96, 881, 935, 873, 792, 92, + 92, 565, 859, 574, 575, 94, 95, 96, 848, 849, + 870, 94, 95, 96, 584, 1248, 858, 412, 872, 1545, + 773, 984, 1369, 865, 661, 662, 663, 664, 665, 666, + 667, 660, 1536, 1610, 670, 1544, 843, 878, 745, 1405, + 648, 649, 647, 850, 851, 852, 911, 1596, 412, 862, + 68, 934, 1536, 1585, 1536, 412, 1536, 1564, 650, 1035, + 936, 1070, 871, 1536, 1535, 1481, 1480, 875, 876, 877, + 1461, 879, 880, 1196, 92, 1467, 412, 362, 361, 364, + 365, 366, 367, 646, 885, 886, 363, 368, 1464, 412, + 1415, 1414, 955, 958, 1411, 1412, 892, 950, 968, 1411, + 1410, 996, 412, 912, 1036, 412, 1038, 92, 92, 1008, + 412, 946, 1196, 944, 1035, 646, 412, 30, 945, 1008, + 1013, 1016, 1017, 1018, 1014, 92, 1015, 1019, 1547, 425, + 1373, 1374, 290, 698, 30, 92, 791, 790, 997, 290, + 70, 290, 1203, 980, 1358, 1413, 1007, 1369, 1204, 290, + 290, 290, 1008, 990, 947, 937, 938, 92, 1369, 1036, + 92, 1034, 1235, 1249, 1034, 1516, 976, 977, 1042, 59, + 405, 92, 567, 946, 1008, 944, 1178, 1177, 996, 1034, + 1002, 1023, 986, 996, 999, 996, 59, 59, 336, 860, + 776, 1003, 30, 1006, 438, 1602, 1498, 438, 998, 1077, + 1472, 1097, 1401, 1031, 1373, 1374, 1379, 1252, 1054, 1455, + 1084, 1085, 1086, 1000, 1013, 1016, 1017, 1018, 1014, 1093, + 1015, 1019, 59, 1088, 1087, 290, 92, 1037, 92, 1307, + 1119, 1041, 1032, 1499, 290, 290, 290, 290, 290, 1040, + 1100, 290, 290, 1619, 59, 290, 92, 1057, 1615, 1098, + 659, 658, 668, 669, 661, 662, 663, 664, 665, 666, + 667, 660, 1403, 290, 670, 1376, 1358, 1279, 290, 893, + 290, 290, 864, 1220, 290, 92, 1378, 1101, 1221, 1218, + 1217, 948, 949, 1216, 1219, 1606, 1121, 1122, 1123, 1124, + 1125, 1454, 1599, 1128, 1129, 1094, 1095, 1130, 1222, 1350, + 1017, 1018, 1185, 744, 1604, 1194, 1193, 911, 963, 1134, + 1270, 1102, 789, 1104, 597, 1132, 1459, 1262, 737, 981, + 1133, 1579, 964, 951, 952, 1578, 1137, 957, 960, 961, + 738, 1131, 659, 658, 668, 669, 661, 662, 663, 664, + 665, 666, 667, 660, 1514, 1260, 670, 1254, 1494, 1103, + 863, 1021, 975, 1192, 418, 978, 979, 406, 407, 1458, + 1156, 1191, 409, 410, 912, 70, 1457, 1142, 419, 1353, + 1078, 1079, 1080, 1081, 1196, 748, 749, 421, 290, 420, + 627, 1621, 1620, 405, 1166, 1163, 1089, 1090, 1091, 290, + 290, 290, 290, 290, 887, 1155, 1210, 1184, 758, 403, + 751, 290, 418, 1621, 1561, 290, 1487, 1189, 1198, 290, + 1201, 1171, 982, 68, 290, 290, 419, 1205, 290, 290, + 290, 73, 65, 415, 416, 421, 1, 420, 312, 1613, + 1188, 1247, 1424, 92, 401, 1495, 1109, 1227, 1580, 1250, + 1529, 1395, 1253, 1197, 1236, 1060, 1258, 1258, 1238, 1199, + 1051, 1212, 1213, 1211, 1215, 870, 1214, 81, 1223, 564, + 80, 1571, 882, 611, 1059, 1058, 1537, 1237, 651, 1233, + 1054, 1234, 1264, 93, 1074, 1259, 1239, 291, 1485, 1402, + 291, 92, 92, 1267, 1268, 93, 1269, 291, 1271, 1272, + 1273, 1242, 1261, 1576, 1255, 1256, 797, 795, 796, 794, + 799, 798, 793, 305, 336, 894, 322, 1020, 785, 1099, + 752, 92, 84, 708, 93, 1300, 1299, 1105, 291, 1071, + 291, 1149, 302, 1276, 1282, 1150, 621, 622, 307, 275, + 678, 1190, 1243, 439, 432, 92, 1157, 1158, 1364, 739, + 742, 934, 1164, 1298, 987, 1167, 1168, 740, 1456, 1352, + 1170, 707, 965, 1174, 1323, 767, 345, 1176, 904, 360, + 1179, 1180, 1181, 1182, 1183, 1151, 1152, 1281, 1343, 357, + 358, 290, 1322, 1324, 1315, 1313, 1314, 991, 1202, 652, + 343, 92, 337, 1337, 766, 759, 1169, 92, 92, 1336, + 1321, 946, 1210, 1347, 1359, 1012, 1312, 1362, 945, 1010, + 1009, 772, 1375, 1371, 765, 995, 414, 1225, 1226, 962, + 1555, 1356, 1451, 92, 413, 1368, 290, 52, 1322, 33, + 327, 635, 422, 1351, 23, 22, 21, 20, 19, 25, + 92, 18, 92, 92, 17, 16, 1258, 1258, 1394, 1377, + 585, 1385, 37, 1387, 27, 1388, 1386, 1384, 26, 15, + 14, 1408, 13, 12, 11, 1398, 10, 9, 5, 4, + 290, 1393, 638, 24, 1399, 1400, 696, 1054, 2, 1054, + 0, 1406, 1407, 0, 0, 0, 0, 0, 0, 0, + 290, 0, 0, 0, 0, 0, 92, 0, 1425, 92, + 92, 92, 290, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1417, 0, 0, 0, 0, 0, 0, 0, + 0, 291, 1416, 0, 0, 0, 291, 1418, 0, 1420, + 0, 0, 291, 0, 0, 0, 0, 0, 291, 0, + 874, 0, 1419, 1434, 1430, 1431, 1319, 1320, 1439, 93, + 0, 93, 0, 0, 1429, 0, 0, 0, 93, 0, + 0, 0, 0, 0, 0, 0, 0, 891, 1210, 0, + 93, 93, 0, 0, 0, 1460, 1469, 1468, 0, 0, + 0, 0, 0, 0, 92, 0, 900, 901, 902, 903, + 1250, 0, 92, 0, 1478, 0, 0, 0, 0, 0, + 0, 0, 0, 1479, 0, 0, 0, 92, 0, 1316, + 0, 0, 0, 0, 92, 0, 0, 0, 0, 0, + 0, 1054, 1380, 0, 0, 1488, 0, 1490, 1502, 659, + 658, 668, 669, 661, 662, 663, 664, 665, 666, 667, + 660, 953, 954, 670, 0, 0, 0, 0, 0, 0, + 0, 1497, 1501, 0, 0, 92, 92, 0, 92, 0, + 0, 1500, 0, 92, 1362, 92, 92, 92, 290, 1513, + 93, 1508, 92, 291, 1515, 291, 291, 1522, 93, 1523, + 1525, 1526, 0, 0, 93, 1527, 1517, 0, 1521, 92, + 290, 1534, 1493, 1541, 0, 0, 0, 0, 1528, 0, + 0, 0, 1542, 1549, 1543, 0, 1436, 1437, 0, 1438, + 0, 0, 1440, 0, 1442, 0, 1433, 0, 1562, 1362, + 1435, 0, 1570, 0, 1048, 1568, 0, 92, 0, 0, + 0, 1444, 1445, 1569, 0, 0, 0, 0, 92, 92, + 0, 0, 1550, 0, 0, 1584, 0, 1583, 0, 0, + 0, 0, 0, 0, 92, 0, 0, 0, 1462, 1463, + 1210, 1466, 1590, 1293, 0, 290, 0, 0, 0, 0, + 0, 0, 0, 92, 0, 1497, 1054, 1482, 0, 1477, + 0, 1598, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1603, 1605, 92, 0, 1289, 1290, 1291, 0, 0, + 0, 0, 0, 0, 0, 1618, 0, 1607, 0, 0, + 291, 0, 374, 29, 1629, 93, 0, 1593, 0, 0, + 291, 291, 93, 93, 93, 0, 0, 0, 291, 0, + 0, 0, 291, 0, 0, 291, 0, 0, 0, 291, + 0, 93, 29, 0, 0, 0, 93, 93, 93, 291, + 93, 93, 658, 668, 669, 661, 662, 663, 664, 665, + 666, 667, 660, 93, 93, 670, 0, 1292, 0, 1524, + 0, 0, 1297, 1294, 1285, 1295, 1288, 0, 1284, 0, + 404, 0, 1286, 1287, 0, 668, 669, 661, 662, 663, + 664, 665, 666, 667, 660, 0, 1296, 670, 1551, 1552, + 1553, 1554, 0, 1558, 0, 1559, 1560, 1173, 371, 0, + 30, 31, 32, 60, 34, 35, 0, 0, 1565, 0, + 1566, 1567, 0, 0, 1186, 1187, 742, 0, 0, 0, + 64, 0, 0, 0, 0, 36, 55, 56, 93, 58, + 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, + 1586, 0, 0, 0, 0, 0, 1448, 0, 45, 324, + 0, 0, 59, 0, 0, 0, 0, 0, 0, 0, + 0, 93, 93, 0, 0, 1595, 659, 658, 668, 669, + 661, 662, 663, 664, 665, 666, 667, 660, 440, 93, + 670, 0, 0, 0, 0, 0, 291, 0, 0, 93, + 0, 0, 0, 291, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 291, 291, 291, 0, 1630, 1631, 0, + 0, 93, 0, 0, 93, 0, 0, 0, 38, 39, + 41, 40, 43, 0, 57, 93, 659, 658, 668, 669, + 661, 662, 663, 664, 665, 666, 667, 660, 0, 0, + 670, 0, 0, 0, 0, 0, 0, 44, 63, 62, + 0, 1447, 53, 54, 42, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 0, 1446, 0, 46, 47, + 0, 48, 49, 50, 51, 0, 0, 0, 0, 291, + 93, 0, 93, 0, 0, 0, 0, 0, 291, 291, + 291, 291, 291, 0, 0, 291, 291, 0, 0, 291, + 93, 0, 1345, 0, 0, 0, 0, 616, 0, 616, + 0, 0, 0, 0, 0, 0, 616, 291, 0, 0, + 0, 0, 291, 0, 291, 291, 1354, 0, 291, 93, + 29, 659, 658, 668, 669, 661, 662, 663, 664, 665, + 666, 667, 660, 679, 681, 670, 659, 658, 668, 669, + 661, 662, 663, 664, 665, 666, 667, 660, 0, 0, + 670, 61, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 694, 0, 0, 0, 699, 700, + 701, 702, 703, 704, 705, 706, 0, 709, 712, 712, + 712, 718, 712, 712, 718, 712, 726, 727, 728, 729, + 730, 731, 732, 440, 0, 440, 0, 29, 0, 0, + 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 634, 636, 0, 0, 0, 0, + 0, 0, 291, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, 0, 0, 291, 0, 0, 0, 291, - 0, 0, 0, 291, 0, 0, 950, 951, 291, 291, - 0, 1451, 291, 291, 291, 0, 0, 0, 0, 0, - 294, 0, 0, 0, 0, 0, 0, 93, 0, 297, - 0, 936, 0, 439, 0, 0, 0, 306, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 966, 0, 0, - 0, 0, 657, 656, 666, 667, 659, 660, 661, 662, - 663, 664, 665, 658, 970, 971, 668, 0, 1430, 0, - 0, 304, 1432, 767, 0, 93, 93, 311, 0, 0, - 0, 0, 989, 1441, 1442, 0, 0, 0, 0, 1045, - 0, 0, 753, 0, 0, 439, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 93, 0, 295, 0, 0, - 1459, 1460, 0, 1463, 439, 0, 288, 439, 0, 0, - 0, 0, 0, 0, 0, 0, 326, 0, 439, 93, - 0, 1474, 0, 0, 308, 298, 0, 309, 310, 317, - 0, 0, 0, 301, 303, 314, 299, 300, 319, 318, - 0, 296, 316, 315, 0, 0, 0, 567, 0, 569, - 0, 0, 0, 0, 0, 291, 0, 0, 0, 0, + 0, 0, 0, 291, 0, 0, 0, 0, 291, 291, + 0, 0, 291, 291, 291, 0, 1453, 0, 0, 94, + 95, 96, 0, 0, 0, 0, 0, 93, 1148, 0, + 0, 0, 0, 336, 0, 0, 0, 0, 0, 0, + 1470, 0, 0, 1471, 0, 0, 1473, 0, 659, 658, + 668, 669, 661, 662, 663, 664, 665, 666, 667, 660, + 0, 0, 670, 0, 755, 0, 0, 0, 0, 0, + 0, 0, 440, 294, 0, 93, 93, 0, 786, 0, + 0, 0, 297, 0, 0, 0, 0, 0, 0, 0, + 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, + 0, 0, 0, 616, 0, 0, 0, 0, 0, 0, + 616, 616, 616, 0, 304, 0, 0, 1512, 336, 93, + 311, 0, 0, 0, 0, 0, 0, 0, 0, 616, + 0, 0, 0, 0, 616, 616, 616, 0, 616, 616, + 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, + 295, 616, 616, 0, 0, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, - 0, 93, 93, 439, 0, 439, 0, 0, 0, 0, - 0, 0, 0, 372, 0, 0, 0, 0, 0, 0, - 0, 0, 439, 0, 0, 0, 0, 93, 0, 0, - 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1521, 0, 1444, 93, 0, 93, 93, 0, 0, - 0, 1135, 0, 0, 0, 0, 289, 0, 0, 320, - 0, 0, 0, 0, 0, 0, 289, 0, 1443, 0, - 1548, 1549, 1550, 1551, 291, 1555, 0, 1556, 1557, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 426, 426, - 1562, 1170, 1563, 1564, 291, 0, 0, 289, 0, 289, - 93, 0, 0, 93, 93, 93, 291, 0, 1183, 1184, - 740, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1583, 657, 656, 666, 667, 659, 660, 661, - 662, 663, 664, 665, 658, 0, 0, 668, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1592, 657, 656, - 666, 667, 659, 660, 661, 662, 663, 664, 665, 658, - 0, 0, 668, 0, 966, 0, 0, 0, 0, 0, - 576, 0, 0, 0, 0, 584, 0, 0, 0, 0, - 0, 591, 0, 0, 0, 0, 0, 593, 93, 1627, - 1628, 0, 0, 0, 0, 0, 93, 0, 0, 1313, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 439, - 0, 93, 0, 0, 1145, 0, 0, 0, 93, 657, - 656, 666, 667, 659, 660, 661, 662, 663, 664, 665, - 658, 0, 0, 668, 657, 656, 666, 667, 659, 660, - 661, 662, 663, 664, 665, 658, 0, 0, 668, 0, - 0, 0, 0, 0, 0, 0, 0, 1277, 439, 93, + 0, 93, 93, 0, 0, 0, 0, 308, 298, 0, + 309, 310, 317, 0, 0, 0, 301, 303, 314, 299, + 300, 319, 318, 0, 296, 316, 315, 93, 0, 440, + 291, 0, 0, 0, 0, 0, 440, 440, 440, 0, + 0, 0, 0, 0, 93, 0, 93, 93, 0, 0, + 0, 0, 0, 0, 0, 440, 0, 0, 0, 0, + 440, 440, 440, 0, 440, 440, 0, 0, 0, 0, + 0, 0, 0, 0, 291, 0, 0, 440, 440, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 291, 0, 0, 0, 0, 654, + 93, 657, 0, 93, 93, 93, 291, 671, 672, 673, + 674, 675, 676, 677, 0, 655, 656, 653, 659, 658, + 668, 669, 661, 662, 663, 664, 665, 666, 667, 660, + 0, 1024, 670, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 939, 0, 440, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 969, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 973, 974, 0, 93, 0, + 0, 0, 0, 0, 0, 0, 93, 0, 0, 0, + 0, 0, 0, 992, 0, 0, 0, 0, 616, 0, + 616, 93, 0, 755, 0, 0, 440, 0, 93, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 616, 0, + 0, 0, 0, 0, 0, 440, 0, 0, 440, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 440, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 93, 0, 93, 0, 0, 0, 0, 93, 0, 93, - 93, 93, 291, 0, 0, 0, 93, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 439, 0, 0, - 289, 0, 0, 93, 291, 289, 1342, 0, 0, 0, - 0, 289, 0, 0, 0, 0, 0, 289, 0, 0, - 0, 439, 0, 0, 0, 0, 0, 0, 0, 0, - 1351, 0, 759, 0, 771, 0, 0, 0, 0, 0, - 0, 93, 439, 0, 0, 0, 0, 0, 0, 0, + 93, 93, 291, 0, 0, 909, 93, 0, 918, 919, + 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, + 930, 931, 932, 93, 291, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 440, 0, 440, 1153, 0, 0, + 404, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 440, 0, 0, 0, 0, 0, + 0, 93, 0, 0, 0, 972, 0, 0, 0, 0, 0, 0, 93, 93, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 812, 0, 0, 0, 439, 93, 0, - 966, 0, 0, 1362, 1364, 0, 0, 0, 0, 291, - 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1364, - 0, 0, 0, 0, 0, 0, 0, 93, 0, 0, - 0, 0, 0, 0, 0, 0, 439, 0, 439, 1394, + 0, 0, 0, 1138, 0, 0, 0, 0, 93, 0, + 768, 0, 0, 0, 0, 0, 0, 1206, 1207, 291, + 0, 768, 768, 768, 768, 768, 0, 93, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1024, 0, 1232, + 0, 0, 0, 0, 0, 0, 768, 93, 0, 0, + 768, 0, 0, 0, 0, 372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, - 0, 0, 0, 0, 0, 0, 0, 800, 0, 0, - 0, 0, 289, 289, 773, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 790, 0, - 0, 0, 1418, 0, 0, 1423, 1424, 1425, 846, 847, - 1450, 0, 0, 0, 0, 0, 856, 0, 813, 771, - 0, 0, 862, 0, 0, 0, 0, 336, 0, 0, - 0, 0, 0, 0, 1467, 0, 875, 1468, 0, 0, - 1470, 0, 0, 0, 826, 829, 830, 831, 832, 833, - 834, 0, 835, 836, 837, 838, 839, 814, 815, 816, - 817, 798, 799, 827, 0, 801, 966, 802, 803, 804, - 805, 806, 807, 808, 809, 810, 811, 818, 819, 820, - 821, 822, 823, 824, 825, 0, 0, 0, 0, 0, - 439, 0, 0, 0, 0, 0, 0, 0, 1481, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 439, 0, 0, 0, 0, 289, 0, - 439, 1509, 336, 0, 0, 0, 0, 0, 289, 289, - 0, 0, 0, 0, 0, 0, 289, 0, 0, 289, - 828, 0, 289, 0, 0, 0, 866, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 289, 0, 0, 0, - 0, 1515, 1516, 0, 1517, 0, 0, 0, 0, 1481, - 0, 1481, 1481, 1481, 0, 0, 0, 0, 1394, 0, - 0, 0, 0, 996, 0, 0, 0, 0, 0, 0, - 1000, 0, 1003, 0, 0, 1481, 0, 0, 0, 0, - 0, 0, 1028, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1572, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 439, 439, 426, 866, 0, 0, - 0, 426, 426, 0, 0, 426, 426, 426, 966, 0, - 1588, 967, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1098, 0, 0, 1594, - 426, 426, 426, 426, 426, 1118, 1119, 1120, 1121, 1122, - 0, 1125, 1126, 0, 0, 1127, 0, 0, 0, 1481, - 0, 0, 0, 289, 0, 0, 0, 0, 0, 866, - 289, 0, 289, 1129, 0, 0, 0, 0, 1130, 0, - 289, 1026, 289, 0, 1134, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 289, 0, + 0, 320, 0, 0, 0, 0, 0, 0, 289, 0, + 0, 0, 0, 0, 616, 0, 969, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 426, 426, 0, 0, 0, 0, 0, 0, 0, 289, + 0, 289, 0, 616, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1143, 1144, + 1145, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1280, + 440, 0, 0, 0, 0, 0, 0, 1363, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 440, + 0, 0, 0, 0, 0, 0, 0, 0, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 289, 0, 0, 0, - 0, 0, 0, 0, 0, 289, 289, 289, 289, 289, - 0, 289, 289, 0, 0, 289, 0, 0, 0, 0, + 0, 0, 0, 0, 440, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 289, 0, 0, 0, 0, 289, 0, - 1132, 1133, 0, 0, 289, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 440, + 0, 0, 969, 0, 0, 1365, 1367, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1234, 0, 0, 0, 0, + 0, 0, 289, 0, 0, 0, 0, 289, 0, 0, + 0, 1367, 0, 289, 0, 0, 0, 0, 0, 289, + 0, 0, 0, 0, 0, 1450, 0, 0, 440, 0, + 440, 1397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 426, 426, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1474, 1475, 1476, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1421, 0, 0, 1426, 1427, 1428, + 1317, 1318, 0, 0, 0, 0, 0, 0, 0, 616, + 0, 0, 0, 0, 0, 1338, 1339, 0, 1340, 1341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1348, 1349, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 426, 289, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 967, 289, - 289, 289, 289, 289, 0, 0, 0, 0, 0, 0, - 0, 1221, 0, 0, 0, 289, 0, 0, 0, 1026, - 0, 0, 0, 0, 289, 289, 0, 0, 289, 1237, - 866, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 426, 0, 0, 0, 1363, 0, 29, 0, 969, 0, + 0, 0, 0, 0, 289, 0, 289, 775, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 440, 0, 0, 0, 0, 1546, 0, 0, + 1484, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 440, 0, 0, 0, 1363, + 0, 0, 440, 0, 0, 1404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1348, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1518, 1519, 0, 1520, 0, 0, 0, + 0, 1484, 0, 1484, 1484, 1484, 0, 0, 0, 1432, + 1397, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1484, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 289, 0, 0, 1616, 0, 0, 0, 0, 0, + 0, 289, 289, 0, 0, 0, 0, 0, 0, 289, + 0, 0, 0, 289, 0, 1575, 289, 0, 0, 0, + 869, 0, 0, 0, 0, 0, 440, 440, 0, 0, + 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 969, 0, 1591, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1597, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1484, 0, 0, 0, 0, 0, 0, 0, 1503, + 1504, 1505, 1506, 1507, 0, 0, 0, 1510, 1511, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 426, 0, 0, 0, 0, 0, - 1413, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 866, 0, 0, 0, - 1416, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 289, 1426, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 967, 0, 0, 0, 0, 0, + 426, 869, 0, 0, 0, 426, 426, 0, 0, 426, + 426, 426, 0, 0, 0, 970, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 426, 426, 426, 426, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 289, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 289, 0, 0, + 0, 0, 0, 869, 289, 0, 289, 0, 0, 0, + 0, 0, 0, 0, 289, 1029, 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1622, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 289, 0, 0, 0, 0, 0, 0, 0, 0, 289, + 289, 289, 289, 289, 0, 0, 289, 289, 0, 0, 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 289, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 289, 0, + 0, 0, 0, 289, 0, 1135, 1136, 0, 0, 289, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 426, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 967, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1547, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 426, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 426, 289, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 970, 289, 289, 289, 289, 289, 0, + 0, 0, 0, 0, 0, 0, 1224, 0, 0, 0, + 289, 0, 0, 0, 1029, 0, 0, 0, 0, 289, + 289, 0, 0, 289, 1240, 869, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1590, 0, 0, 0, 0, - 0, 0, 549, 537, 0, 0, 494, 552, 467, 484, - 560, 485, 488, 525, 452, 507, 184, 482, 1026, 471, - 447, 478, 448, 469, 496, 126, 500, 466, 539, 510, - 551, 155, 0, 472, 558, 158, 516, 0, 231, 172, - 289, 0, 0, 498, 541, 505, 534, 493, 526, 457, - 515, 553, 483, 523, 554, 0, 0, 0, 94, 95, - 96, 0, 1052, 1053, 0, 0, 0, 0, 0, 116, - 0, 520, 548, 480, 522, 524, 562, 446, 517, 0, - 450, 453, 559, 544, 475, 476, 1248, 0, 0, 0, - 0, 0, 0, 497, 506, 531, 491, 0, 0, 0, - 0, 0, 967, 0, 0, 473, 0, 514, 0, 0, - 0, 454, 451, 0, 0, 289, 0, 495, 0, 0, - 0, 456, 0, 474, 532, 0, 444, 135, 536, 543, - 492, 292, 547, 490, 489, 550, 203, 0, 235, 139, - 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, - 540, 470, 479, 120, 477, 213, 191, 252, 513, 193, - 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, - 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, - 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, - 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, - 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, - 153, 129, 141, 201, 161, 202, 142, 174, 173, 175, - 0, 449, 0, 232, 255, 274, 114, 465, 239, 266, - 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, - 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, - 190, 214, 118, 254, 230, 461, 464, 459, 460, 508, - 509, 555, 556, 557, 533, 455, 0, 462, 463, 0, - 538, 545, 546, 512, 97, 106, 157, 271, 206, 131, - 256, 445, 458, 124, 468, 0, 0, 481, 486, 487, - 499, 501, 502, 503, 504, 511, 518, 519, 521, 527, - 528, 529, 530, 535, 542, 561, 99, 100, 107, 113, - 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, - 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, - 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, - 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, - 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, - 260, 263, 138, 250, 264, 549, 537, 0, 0, 494, - 552, 467, 484, 560, 485, 488, 525, 452, 507, 184, - 482, 0, 471, 447, 478, 448, 469, 496, 126, 500, - 466, 539, 510, 551, 155, 0, 472, 558, 158, 516, - 0, 231, 172, 0, 0, 0, 498, 541, 505, 534, - 493, 526, 457, 515, 553, 483, 523, 554, 0, 0, - 0, 94, 95, 96, 0, 1052, 1053, 0, 0, 0, - 0, 0, 116, 0, 520, 548, 480, 522, 524, 562, - 446, 517, 0, 450, 453, 559, 544, 475, 476, 0, - 0, 0, 0, 0, 0, 0, 497, 506, 531, 491, - 0, 0, 0, 0, 0, 0, 0, 0, 473, 0, - 514, 0, 0, 0, 454, 451, 0, 0, 0, 0, - 495, 0, 0, 0, 456, 0, 474, 532, 0, 444, - 135, 536, 543, 492, 292, 547, 490, 489, 550, 203, - 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, - 181, 211, 215, 540, 470, 479, 120, 477, 213, 191, - 252, 513, 193, 212, 159, 241, 204, 251, 261, 262, - 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, - 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, - 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, - 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, - 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, - 174, 173, 175, 0, 449, 0, 232, 255, 274, 114, - 465, 239, 266, 269, 0, 205, 115, 134, 128, 200, - 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, - 160, 208, 272, 190, 214, 118, 254, 230, 461, 464, - 459, 460, 508, 509, 555, 556, 557, 533, 455, 0, - 462, 463, 0, 538, 545, 546, 512, 97, 106, 157, - 271, 206, 131, 256, 445, 458, 124, 468, 0, 0, - 481, 486, 487, 499, 501, 502, 503, 504, 511, 518, - 519, 521, 527, 528, 529, 530, 535, 542, 561, 99, - 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, - 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, - 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, - 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, - 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, - 242, 243, 253, 260, 263, 138, 250, 264, 549, 537, - 0, 0, 494, 552, 467, 484, 560, 485, 488, 525, - 452, 507, 184, 482, 0, 471, 447, 478, 448, 469, - 496, 126, 500, 466, 539, 510, 551, 155, 0, 472, - 558, 158, 516, 0, 231, 172, 0, 0, 0, 498, - 541, 505, 534, 493, 526, 457, 515, 553, 483, 523, - 554, 59, 0, 0, 94, 95, 96, 0, 0, 0, - 0, 0, 0, 0, 0, 116, 0, 520, 548, 480, - 522, 524, 562, 446, 517, 0, 450, 453, 559, 544, - 475, 476, 0, 0, 0, 0, 0, 0, 0, 497, - 506, 531, 491, 0, 0, 0, 0, 0, 0, 0, - 0, 473, 0, 514, 0, 0, 0, 454, 451, 0, - 0, 0, 0, 495, 0, 0, 0, 456, 0, 474, - 532, 0, 444, 135, 536, 543, 492, 292, 547, 490, - 489, 550, 203, 0, 235, 139, 154, 112, 151, 98, - 108, 0, 137, 181, 211, 215, 540, 470, 479, 120, - 477, 213, 191, 252, 513, 193, 212, 159, 241, 204, - 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, - 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, - 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, - 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, - 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, - 161, 202, 142, 174, 173, 175, 0, 449, 0, 232, - 255, 274, 114, 465, 239, 266, 269, 0, 205, 115, - 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, - 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, - 230, 461, 464, 459, 460, 508, 509, 555, 556, 557, - 533, 455, 0, 462, 463, 0, 538, 545, 546, 512, - 97, 106, 157, 271, 206, 131, 256, 445, 458, 124, - 468, 0, 0, 481, 486, 487, 499, 501, 502, 503, - 504, 511, 518, 519, 521, 527, 528, 529, 530, 535, - 542, 561, 99, 100, 107, 113, 119, 123, 127, 130, - 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, - 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, - 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, - 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, - 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, - 264, 549, 537, 0, 0, 494, 552, 467, 484, 560, - 485, 488, 525, 452, 507, 184, 482, 0, 471, 447, - 478, 448, 469, 496, 126, 500, 466, 539, 510, 551, - 155, 0, 472, 558, 158, 516, 0, 231, 172, 0, - 0, 0, 498, 541, 505, 534, 493, 526, 457, 515, - 553, 483, 523, 554, 0, 0, 0, 94, 95, 96, - 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, - 520, 548, 480, 522, 524, 562, 446, 517, 0, 450, - 453, 559, 544, 475, 476, 0, 0, 0, 0, 0, - 0, 0, 497, 506, 531, 491, 0, 0, 0, 0, - 0, 0, 1352, 0, 473, 0, 514, 0, 0, 0, - 454, 451, 0, 0, 0, 0, 495, 0, 0, 0, - 456, 0, 474, 532, 0, 444, 135, 536, 543, 492, - 292, 547, 490, 489, 550, 203, 0, 235, 139, 154, - 112, 151, 98, 108, 0, 137, 181, 211, 215, 540, - 470, 479, 120, 477, 213, 191, 252, 513, 193, 212, - 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, - 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, - 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, - 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, - 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, - 129, 141, 201, 161, 202, 142, 174, 173, 175, 0, - 449, 0, 232, 255, 274, 114, 465, 239, 266, 269, - 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, - 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, - 214, 118, 254, 230, 461, 464, 459, 460, 508, 509, - 555, 556, 557, 533, 455, 0, 462, 463, 0, 538, - 545, 546, 512, 97, 106, 157, 271, 206, 131, 256, - 445, 458, 124, 468, 0, 0, 481, 486, 487, 499, - 501, 502, 503, 504, 511, 518, 519, 521, 527, 528, - 529, 530, 535, 542, 561, 99, 100, 107, 113, 119, - 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, - 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, - 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, - 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, - 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, - 263, 138, 250, 264, 549, 537, 0, 0, 494, 552, - 467, 484, 560, 485, 488, 525, 452, 507, 184, 482, - 0, 471, 447, 478, 448, 469, 496, 126, 500, 466, - 539, 510, 551, 155, 0, 472, 558, 158, 516, 0, - 231, 172, 0, 0, 0, 498, 541, 505, 534, 493, - 526, 457, 515, 553, 483, 523, 554, 0, 0, 0, - 94, 95, 96, 0, 0, 0, 0, 0, 0, 0, - 0, 116, 0, 520, 548, 480, 522, 524, 562, 446, - 517, 0, 450, 453, 559, 544, 475, 476, 0, 0, - 0, 0, 0, 0, 0, 497, 506, 531, 491, 0, - 0, 0, 0, 0, 0, 1238, 0, 473, 0, 514, - 0, 0, 0, 454, 451, 0, 0, 0, 0, 495, - 0, 0, 0, 456, 0, 474, 532, 0, 444, 135, - 536, 543, 492, 292, 547, 490, 489, 550, 203, 0, - 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, - 211, 215, 540, 470, 479, 120, 477, 213, 191, 252, - 513, 193, 212, 159, 241, 204, 251, 261, 262, 238, - 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, - 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, - 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, - 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, - 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, - 173, 175, 0, 449, 0, 232, 255, 274, 114, 465, - 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, - 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, - 208, 272, 190, 214, 118, 254, 230, 461, 464, 459, - 460, 508, 509, 555, 556, 557, 533, 455, 0, 462, - 463, 0, 538, 545, 546, 512, 97, 106, 157, 271, - 206, 131, 256, 445, 458, 124, 468, 0, 0, 481, - 486, 487, 499, 501, 502, 503, 504, 511, 518, 519, - 521, 527, 528, 529, 530, 535, 542, 561, 99, 100, - 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, - 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, - 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, - 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, - 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, - 243, 253, 260, 263, 138, 250, 264, 549, 537, 0, - 0, 494, 552, 467, 484, 560, 485, 488, 525, 452, - 507, 184, 482, 0, 471, 447, 478, 448, 469, 496, - 126, 500, 466, 539, 510, 551, 155, 0, 472, 558, - 158, 516, 0, 231, 172, 0, 0, 0, 498, 541, - 505, 534, 493, 526, 457, 515, 553, 483, 523, 554, - 0, 0, 0, 94, 95, 96, 0, 0, 0, 0, - 0, 0, 0, 0, 116, 0, 520, 548, 480, 522, - 524, 562, 446, 517, 0, 450, 453, 559, 544, 475, - 476, 0, 0, 0, 0, 0, 0, 0, 497, 506, - 531, 491, 0, 0, 0, 0, 0, 0, 998, 0, - 473, 0, 514, 0, 0, 0, 454, 451, 0, 0, - 0, 0, 495, 0, 0, 0, 456, 0, 474, 532, - 0, 444, 135, 536, 543, 492, 292, 547, 490, 489, - 550, 203, 0, 235, 139, 154, 112, 151, 98, 108, - 0, 137, 181, 211, 215, 540, 470, 479, 120, 477, - 213, 191, 252, 513, 193, 212, 159, 241, 204, 251, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 426, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 869, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 289, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 970, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 289, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 289, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 289, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 289, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 970, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 550, 538, 0, + 0, 495, 553, 468, 485, 561, 486, 489, 526, 453, + 508, 184, 483, 1029, 472, 448, 479, 449, 470, 497, + 126, 501, 467, 540, 511, 552, 155, 0, 473, 559, + 158, 517, 0, 231, 172, 289, 0, 0, 499, 542, + 506, 535, 494, 527, 458, 516, 554, 484, 524, 555, + 0, 0, 0, 94, 95, 96, 0, 1055, 1056, 0, + 0, 0, 0, 0, 116, 0, 521, 549, 481, 523, + 525, 563, 447, 518, 0, 451, 454, 560, 545, 476, + 477, 1251, 0, 0, 0, 0, 0, 0, 498, 507, + 532, 492, 0, 0, 0, 0, 0, 970, 0, 0, + 474, 0, 515, 0, 0, 0, 455, 452, 0, 0, + 289, 0, 496, 0, 0, 0, 457, 0, 475, 533, + 0, 445, 135, 537, 544, 493, 292, 548, 491, 490, + 551, 203, 0, 235, 139, 154, 112, 151, 98, 108, + 0, 137, 181, 211, 215, 541, 471, 480, 120, 478, + 213, 191, 252, 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, - 202, 142, 174, 173, 175, 0, 449, 0, 232, 255, - 274, 114, 465, 239, 266, 269, 0, 205, 115, 134, + 202, 142, 174, 173, 175, 0, 450, 0, 232, 255, + 274, 114, 466, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, 230, - 461, 464, 459, 460, 508, 509, 555, 556, 557, 533, - 455, 0, 462, 463, 0, 538, 545, 546, 512, 97, - 106, 157, 271, 206, 131, 256, 445, 458, 124, 468, - 0, 0, 481, 486, 487, 499, 501, 502, 503, 504, - 511, 518, 519, 521, 527, 528, 529, 530, 535, 542, - 561, 99, 100, 107, 113, 119, 123, 127, 130, 136, + 462, 465, 460, 461, 509, 510, 556, 557, 558, 534, + 456, 0, 463, 464, 0, 539, 546, 547, 513, 97, + 106, 157, 271, 206, 131, 256, 446, 459, 124, 469, + 0, 0, 482, 487, 488, 500, 502, 503, 504, 505, + 512, 519, 520, 522, 528, 529, 530, 531, 536, 543, + 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, - 549, 537, 0, 0, 494, 552, 467, 484, 560, 485, - 488, 525, 452, 507, 184, 482, 0, 471, 447, 478, - 448, 469, 496, 126, 500, 466, 539, 510, 551, 155, - 0, 472, 558, 158, 516, 0, 231, 172, 0, 0, - 0, 498, 541, 505, 534, 493, 526, 457, 515, 553, - 483, 523, 554, 0, 0, 0, 94, 95, 96, 0, - 0, 0, 0, 0, 0, 0, 0, 116, 0, 520, - 548, 480, 522, 524, 562, 446, 517, 0, 450, 453, - 559, 544, 475, 476, 0, 0, 0, 0, 0, 0, - 0, 497, 506, 531, 491, 0, 0, 0, 0, 0, - 0, 0, 0, 473, 0, 514, 0, 0, 0, 454, - 451, 0, 0, 0, 0, 495, 0, 0, 0, 456, - 0, 474, 532, 0, 444, 135, 536, 543, 492, 292, - 547, 490, 489, 550, 203, 0, 235, 139, 154, 112, - 151, 98, 108, 0, 137, 181, 211, 215, 540, 470, - 479, 120, 477, 213, 191, 252, 513, 193, 212, 159, + 550, 538, 0, 0, 495, 553, 468, 485, 561, 486, + 489, 526, 453, 508, 184, 483, 0, 472, 448, 479, + 449, 470, 497, 126, 501, 467, 540, 511, 552, 155, + 0, 473, 559, 158, 517, 0, 231, 172, 0, 0, + 0, 499, 542, 506, 535, 494, 527, 458, 516, 554, + 484, 524, 555, 0, 0, 0, 94, 95, 96, 0, + 1055, 1056, 0, 0, 0, 0, 0, 116, 0, 521, + 549, 481, 523, 525, 563, 447, 518, 0, 451, 454, + 560, 545, 476, 477, 0, 0, 0, 0, 0, 0, + 0, 498, 507, 532, 492, 0, 0, 0, 0, 0, + 0, 0, 0, 474, 0, 515, 0, 0, 0, 455, + 452, 0, 0, 0, 0, 496, 0, 0, 0, 457, + 0, 475, 533, 0, 445, 135, 537, 544, 493, 292, + 548, 491, 490, 551, 203, 0, 235, 139, 154, 112, + 151, 98, 108, 0, 137, 181, 211, 215, 541, 471, + 480, 120, 478, 213, 191, 252, 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, - 141, 201, 161, 202, 142, 174, 173, 175, 0, 449, - 0, 232, 255, 274, 114, 465, 239, 266, 269, 0, + 141, 201, 161, 202, 142, 174, 173, 175, 0, 450, + 0, 232, 255, 274, 114, 466, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, - 118, 254, 230, 461, 464, 459, 460, 508, 509, 555, - 556, 557, 533, 455, 0, 462, 463, 0, 538, 545, - 546, 512, 97, 106, 157, 271, 206, 131, 256, 445, - 458, 124, 468, 0, 0, 481, 486, 487, 499, 501, - 502, 503, 504, 511, 518, 519, 521, 527, 528, 529, - 530, 535, 542, 561, 99, 100, 107, 113, 119, 123, + 118, 254, 230, 462, 465, 460, 461, 509, 510, 556, + 557, 558, 534, 456, 0, 463, 464, 0, 539, 546, + 547, 513, 97, 106, 157, 271, 206, 131, 256, 446, + 459, 124, 469, 0, 0, 482, 487, 488, 500, 502, + 503, 504, 505, 512, 519, 520, 522, 528, 529, 530, + 531, 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, - 138, 250, 264, 549, 537, 0, 0, 494, 552, 467, - 484, 560, 485, 488, 525, 452, 507, 184, 482, 0, - 471, 447, 478, 448, 469, 496, 126, 500, 466, 539, - 510, 551, 155, 0, 472, 558, 158, 516, 0, 231, - 172, 0, 0, 0, 498, 541, 505, 534, 493, 526, - 457, 515, 553, 483, 523, 554, 0, 0, 0, 94, + 138, 250, 264, 550, 538, 0, 0, 495, 553, 468, + 485, 561, 486, 489, 526, 453, 508, 184, 483, 0, + 472, 448, 479, 449, 470, 497, 126, 501, 467, 540, + 511, 552, 155, 0, 473, 559, 158, 517, 0, 231, + 172, 0, 0, 0, 499, 542, 506, 535, 494, 527, + 458, 516, 554, 484, 524, 555, 59, 0, 0, 94, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, - 116, 0, 520, 548, 480, 522, 524, 562, 446, 517, - 0, 450, 453, 559, 544, 475, 476, 0, 0, 0, - 0, 0, 0, 0, 497, 506, 531, 491, 0, 0, - 0, 0, 0, 0, 0, 0, 473, 0, 514, 0, - 0, 0, 454, 451, 0, 0, 0, 0, 495, 0, - 0, 0, 456, 0, 474, 532, 0, 444, 135, 536, - 543, 492, 292, 547, 490, 489, 550, 203, 0, 235, + 116, 0, 521, 549, 481, 523, 525, 563, 447, 518, + 0, 451, 454, 560, 545, 476, 477, 0, 0, 0, + 0, 0, 0, 0, 498, 507, 532, 492, 0, 0, + 0, 0, 0, 0, 0, 0, 474, 0, 515, 0, + 0, 0, 455, 452, 0, 0, 0, 0, 496, 0, + 0, 0, 457, 0, 475, 533, 0, 445, 135, 537, + 544, 493, 292, 548, 491, 490, 551, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, - 215, 540, 470, 479, 120, 477, 213, 191, 252, 513, + 215, 541, 471, 480, 120, 478, 213, 191, 252, 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, - 442, 257, 177, 240, 248, 171, 164, 104, 246, 169, + 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, 173, - 175, 0, 449, 0, 232, 255, 274, 114, 465, 239, + 175, 0, 450, 0, 232, 255, 274, 114, 466, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, - 265, 267, 268, 443, 441, 436, 435, 152, 160, 208, - 272, 190, 214, 118, 254, 230, 461, 464, 459, 460, - 508, 509, 555, 556, 557, 533, 455, 0, 462, 463, - 0, 538, 545, 546, 512, 97, 106, 157, 271, 206, - 131, 256, 445, 458, 124, 468, 0, 0, 481, 486, - 487, 499, 501, 502, 503, 504, 511, 518, 519, 521, - 527, 528, 529, 530, 535, 542, 561, 99, 100, 107, + 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, + 272, 190, 214, 118, 254, 230, 462, 465, 460, 461, + 509, 510, 556, 557, 558, 534, 456, 0, 463, 464, + 0, 539, 546, 547, 513, 97, 106, 157, 271, 206, + 131, 256, 446, 459, 124, 469, 0, 0, 482, 487, + 488, 500, 502, 503, 504, 505, 512, 519, 520, 522, + 528, 529, 530, 531, 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, - 253, 260, 263, 138, 250, 264, 549, 537, 0, 0, - 494, 552, 467, 484, 560, 485, 488, 525, 452, 507, - 184, 482, 0, 471, 447, 478, 448, 469, 496, 126, - 500, 466, 539, 510, 551, 155, 0, 472, 558, 158, - 516, 0, 231, 172, 0, 0, 0, 498, 541, 505, - 534, 493, 526, 457, 515, 553, 483, 523, 554, 0, + 253, 260, 263, 138, 250, 264, 550, 538, 0, 0, + 495, 553, 468, 485, 561, 486, 489, 526, 453, 508, + 184, 483, 0, 472, 448, 479, 449, 470, 497, 126, + 501, 467, 540, 511, 552, 155, 0, 473, 559, 158, + 517, 0, 231, 172, 0, 0, 0, 499, 542, 506, + 535, 494, 527, 458, 516, 554, 484, 524, 555, 0, 0, 0, 94, 95, 96, 0, 0, 0, 0, 0, - 0, 0, 0, 116, 0, 520, 548, 480, 522, 524, - 562, 446, 517, 0, 450, 453, 559, 544, 475, 476, - 0, 0, 0, 0, 0, 0, 0, 497, 506, 531, - 491, 0, 0, 0, 0, 0, 0, 0, 0, 473, - 0, 514, 0, 0, 0, 454, 451, 0, 0, 0, - 0, 495, 0, 0, 0, 456, 0, 474, 532, 0, - 444, 135, 536, 543, 492, 292, 547, 490, 489, 550, + 0, 0, 0, 116, 0, 521, 549, 481, 523, 525, + 563, 447, 518, 0, 451, 454, 560, 545, 476, 477, + 0, 0, 0, 0, 0, 0, 0, 498, 507, 532, + 492, 0, 0, 0, 0, 0, 0, 1355, 0, 474, + 0, 515, 0, 0, 0, 455, 452, 0, 0, 0, + 0, 496, 0, 0, 0, 457, 0, 475, 533, 0, + 445, 135, 537, 544, 493, 292, 548, 491, 490, 551, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, - 137, 181, 211, 215, 540, 470, 479, 120, 477, 213, - 191, 252, 513, 193, 212, 159, 241, 204, 251, 261, - 262, 238, 259, 270, 228, 101, 237, 775, 117, 223, + 137, 181, 211, 215, 541, 471, 480, 120, 478, 213, + 191, 252, 514, 193, 212, 159, 241, 204, 251, 261, + 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, - 109, 258, 105, 442, 257, 177, 240, 248, 171, 164, + 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, - 142, 174, 173, 175, 0, 449, 0, 232, 255, 274, - 114, 465, 239, 266, 269, 0, 205, 115, 134, 128, - 200, 132, 156, 265, 267, 268, 443, 441, 436, 435, - 152, 160, 208, 272, 190, 214, 118, 254, 230, 461, - 464, 459, 460, 508, 509, 555, 556, 557, 533, 455, - 0, 462, 463, 0, 538, 545, 546, 512, 97, 106, - 157, 271, 206, 131, 256, 445, 458, 124, 468, 0, - 0, 481, 486, 487, 499, 501, 502, 503, 504, 511, - 518, 519, 521, 527, 528, 529, 530, 535, 542, 561, + 142, 174, 173, 175, 0, 450, 0, 232, 255, 274, + 114, 466, 239, 266, 269, 0, 205, 115, 134, 128, + 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, + 152, 160, 208, 272, 190, 214, 118, 254, 230, 462, + 465, 460, 461, 509, 510, 556, 557, 558, 534, 456, + 0, 463, 464, 0, 539, 546, 547, 513, 97, 106, + 157, 271, 206, 131, 256, 446, 459, 124, 469, 0, + 0, 482, 487, 488, 500, 502, 503, 504, 505, 512, + 519, 520, 522, 528, 529, 530, 531, 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, - 236, 242, 243, 253, 260, 263, 138, 250, 264, 549, - 537, 0, 0, 494, 552, 467, 484, 560, 485, 488, - 525, 452, 507, 184, 482, 0, 471, 447, 478, 448, - 469, 496, 126, 500, 466, 539, 510, 551, 155, 0, - 472, 558, 158, 516, 0, 231, 172, 0, 0, 0, - 498, 541, 505, 534, 493, 526, 457, 515, 553, 483, - 523, 554, 0, 0, 0, 94, 95, 96, 0, 0, - 0, 0, 0, 0, 0, 0, 116, 0, 520, 548, - 480, 522, 524, 562, 446, 517, 0, 450, 453, 559, - 544, 475, 476, 0, 0, 0, 0, 0, 0, 0, - 497, 506, 531, 491, 0, 0, 0, 0, 0, 0, - 0, 0, 473, 0, 514, 0, 0, 0, 454, 451, - 0, 0, 0, 0, 495, 0, 0, 0, 456, 0, - 474, 532, 0, 444, 135, 536, 543, 492, 292, 547, - 490, 489, 550, 203, 0, 235, 139, 154, 112, 151, - 98, 108, 0, 137, 181, 211, 215, 540, 470, 479, - 120, 477, 213, 191, 252, 513, 193, 212, 159, 241, + 236, 242, 243, 253, 260, 263, 138, 250, 264, 550, + 538, 0, 0, 495, 553, 468, 485, 561, 486, 489, + 526, 453, 508, 184, 483, 0, 472, 448, 479, 449, + 470, 497, 126, 501, 467, 540, 511, 552, 155, 0, + 473, 559, 158, 517, 0, 231, 172, 0, 0, 0, + 499, 542, 506, 535, 494, 527, 458, 516, 554, 484, + 524, 555, 0, 0, 0, 94, 95, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 116, 0, 521, 549, + 481, 523, 525, 563, 447, 518, 0, 451, 454, 560, + 545, 476, 477, 0, 0, 0, 0, 0, 0, 0, + 498, 507, 532, 492, 0, 0, 0, 0, 0, 0, + 1241, 0, 474, 0, 515, 0, 0, 0, 455, 452, + 0, 0, 0, 0, 496, 0, 0, 0, 457, 0, + 475, 533, 0, 445, 135, 537, 544, 493, 292, 548, + 491, 490, 551, 203, 0, 235, 139, 154, 112, 151, + 98, 108, 0, 137, 181, 211, 215, 541, 471, 480, + 120, 478, 213, 191, 252, 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, - 433, 117, 223, 0, 0, 0, 103, 247, 234, 170, + 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, - 245, 121, 273, 109, 258, 105, 442, 257, 177, 240, + 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, - 201, 161, 202, 142, 174, 173, 175, 0, 449, 0, - 232, 255, 274, 114, 465, 239, 266, 269, 0, 205, - 115, 134, 128, 200, 132, 156, 265, 267, 268, 443, - 441, 436, 435, 152, 160, 208, 272, 190, 214, 118, - 254, 230, 461, 464, 459, 460, 508, 509, 555, 556, - 557, 533, 455, 0, 462, 463, 0, 538, 545, 546, - 512, 97, 106, 157, 271, 206, 131, 256, 445, 458, - 124, 468, 0, 0, 481, 486, 487, 499, 501, 502, - 503, 504, 511, 518, 519, 521, 527, 528, 529, 530, - 535, 542, 561, 99, 100, 107, 113, 119, 123, 127, + 201, 161, 202, 142, 174, 173, 175, 0, 450, 0, + 232, 255, 274, 114, 466, 239, 266, 269, 0, 205, + 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, + 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, + 254, 230, 462, 465, 460, 461, 509, 510, 556, 557, + 558, 534, 456, 0, 463, 464, 0, 539, 546, 547, + 513, 97, 106, 157, 271, 206, 131, 256, 446, 459, + 124, 469, 0, 0, 482, 487, 488, 500, 502, 503, + 504, 505, 512, 519, 520, 522, 528, 529, 530, 531, + 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, - 250, 264, 184, 0, 0, 938, 0, 341, 0, 0, - 0, 126, 0, 340, 0, 0, 0, 155, 0, 939, - 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, - 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, - 0, 59, 0, 0, 94, 95, 96, 362, 361, 364, - 365, 366, 367, 0, 0, 116, 363, 368, 369, 370, - 0, 0, 0, 0, 338, 355, 0, 383, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 353, 424, - 0, 0, 0, 398, 0, 354, 0, 0, 347, 348, - 350, 349, 351, 356, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 135, 397, 0, 0, 292, 0, 0, - 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, - 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, - 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, - 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, - 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, - 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, - 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, - 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, - 161, 202, 142, 174, 173, 175, 0, 0, 0, 232, - 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, - 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, - 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, - 230, 385, 396, 391, 392, 389, 390, 388, 387, 386, - 399, 377, 378, 379, 380, 382, 0, 393, 394, 381, - 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 99, 100, 107, 113, 119, 123, 127, 130, - 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, - 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, - 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, - 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, - 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, - 264, 184, 0, 0, 0, 0, 341, 0, 0, 0, - 126, 0, 340, 0, 0, 0, 155, 0, 0, 384, - 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, - 375, 376, 0, 0, 0, 0, 0, 0, 1043, 0, - 59, 0, 0, 94, 95, 96, 362, 361, 364, 365, - 366, 367, 0, 0, 116, 363, 368, 369, 370, 1044, - 0, 0, 0, 338, 355, 0, 383, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 352, 353, 0, 0, - 0, 0, 398, 0, 354, 0, 0, 347, 348, 350, - 349, 351, 356, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 135, 397, 0, 0, 292, 0, 0, 395, - 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, - 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, - 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, - 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, - 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, - 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, - 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, - 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, - 202, 142, 174, 173, 175, 0, 0, 0, 232, 255, - 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, - 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, - 229, 152, 160, 208, 272, 190, 214, 118, 254, 230, - 385, 396, 391, 392, 389, 390, 388, 387, 386, 399, - 377, 378, 379, 380, 382, 0, 393, 394, 381, 97, - 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 99, 100, 107, 113, 119, 123, 127, 130, 136, - 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, - 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, - 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, - 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, - 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, - 184, 0, 0, 0, 0, 341, 0, 0, 0, 126, - 0, 340, 0, 0, 0, 155, 0, 0, 384, 158, - 0, 0, 231, 172, 0, 0, 0, 0, 0, 375, - 376, 0, 0, 0, 0, 0, 0, 0, 0, 59, - 0, 412, 94, 95, 96, 362, 361, 364, 365, 366, - 367, 0, 0, 116, 363, 368, 369, 370, 0, 0, - 0, 0, 338, 355, 0, 383, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 352, 353, 0, 0, 0, - 0, 398, 0, 354, 0, 0, 347, 348, 350, 349, - 351, 356, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 135, 397, 0, 0, 292, 0, 0, 395, 0, - 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, - 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, - 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, - 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, - 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, - 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, - 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, - 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, - 142, 174, 173, 175, 0, 0, 0, 232, 255, 274, - 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, - 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, - 152, 160, 208, 272, 190, 214, 118, 254, 230, 385, - 396, 391, 392, 389, 390, 388, 387, 386, 399, 377, - 378, 379, 380, 382, 0, 393, 394, 381, 97, 106, - 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, - 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, - 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, - 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, - 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, - 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, - 0, 0, 0, 0, 341, 0, 0, 0, 126, 0, - 340, 0, 0, 0, 155, 0, 0, 384, 158, 0, - 0, 231, 172, 0, 0, 0, 0, 0, 375, 376, - 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, - 0, 94, 95, 96, 362, 361, 364, 365, 366, 367, - 0, 0, 116, 363, 368, 369, 370, 0, 0, 0, - 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 353, 424, 0, 0, 0, - 398, 0, 354, 0, 0, 347, 348, 350, 349, 351, - 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 135, 397, 0, 0, 292, 0, 0, 395, 0, 203, - 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, - 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, - 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, - 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, - 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, - 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, - 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, - 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, - 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, - 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, - 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, - 160, 208, 272, 190, 214, 118, 254, 230, 385, 396, - 391, 392, 389, 390, 388, 387, 386, 399, 377, 378, - 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, - 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, - 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, - 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, - 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, - 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, - 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, - 0, 0, 0, 341, 0, 0, 0, 126, 0, 340, - 0, 0, 0, 155, 0, 0, 384, 158, 0, 0, - 231, 172, 0, 0, 0, 0, 0, 375, 376, 0, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, - 94, 95, 96, 362, 956, 364, 365, 366, 367, 0, - 0, 116, 363, 368, 369, 370, 0, 0, 0, 0, - 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 352, 353, 424, 0, 0, 0, 398, - 0, 354, 0, 0, 347, 348, 350, 349, 351, 356, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, - 397, 0, 0, 292, 0, 0, 395, 0, 203, 0, - 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, - 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, - 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, - 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, - 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, - 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, - 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, - 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, - 173, 175, 0, 0, 0, 232, 255, 274, 114, 0, - 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, - 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, - 208, 272, 190, 214, 118, 254, 230, 385, 396, 391, - 392, 389, 390, 388, 387, 386, 399, 377, 378, 379, - 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, - 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, - 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, - 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, - 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, - 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, - 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, - 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, - 0, 0, 341, 0, 0, 0, 126, 0, 340, 0, - 0, 0, 155, 0, 0, 384, 158, 0, 0, 231, - 172, 0, 0, 0, 0, 0, 375, 376, 0, 0, - 0, 0, 0, 0, 0, 0, 59, 0, 0, 94, - 95, 96, 362, 953, 364, 365, 366, 367, 0, 0, - 116, 363, 368, 369, 370, 0, 0, 0, 0, 338, - 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 352, 353, 424, 0, 0, 0, 398, 0, - 354, 0, 0, 347, 348, 350, 349, 351, 356, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 135, 397, - 0, 0, 292, 0, 0, 395, 0, 203, 0, 235, - 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, - 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, - 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, - 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, - 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, - 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, - 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, - 163, 153, 129, 141, 201, 161, 202, 142, 174, 173, - 175, 0, 0, 0, 232, 255, 274, 114, 0, 239, - 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, - 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, - 272, 190, 214, 118, 254, 230, 385, 396, 391, 392, - 389, 390, 388, 387, 386, 399, 377, 378, 379, 380, - 382, 0, 393, 394, 381, 97, 106, 157, 271, 206, - 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 99, 100, 107, - 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, - 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, - 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, - 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, - 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, - 253, 260, 263, 138, 250, 264, 405, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, - 0, 0, 0, 0, 341, 0, 0, 0, 126, 0, - 340, 0, 0, 0, 155, 0, 0, 384, 158, 0, - 0, 231, 172, 0, 0, 0, 0, 0, 375, 376, - 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, - 0, 94, 95, 96, 362, 361, 364, 365, 366, 367, - 0, 0, 116, 363, 368, 369, 370, 0, 0, 0, - 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 352, 353, 0, 0, 0, 0, - 398, 0, 354, 0, 0, 347, 348, 350, 349, 351, - 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 135, 397, 0, 0, 292, 0, 0, 395, 0, 203, + 250, 264, 550, 538, 0, 0, 495, 553, 468, 485, + 561, 486, 489, 526, 453, 508, 184, 483, 0, 472, + 448, 479, 449, 470, 497, 126, 501, 467, 540, 511, + 552, 155, 0, 473, 559, 158, 517, 0, 231, 172, + 0, 0, 0, 499, 542, 506, 535, 494, 527, 458, + 516, 554, 484, 524, 555, 0, 0, 0, 94, 95, + 96, 0, 0, 0, 0, 0, 0, 0, 0, 116, + 0, 521, 549, 481, 523, 525, 563, 447, 518, 0, + 451, 454, 560, 545, 476, 477, 0, 0, 0, 0, + 0, 0, 0, 498, 507, 532, 492, 0, 0, 0, + 0, 0, 0, 1001, 0, 474, 0, 515, 0, 0, + 0, 455, 452, 0, 0, 0, 0, 496, 0, 0, + 0, 457, 0, 475, 533, 0, 445, 135, 537, 544, + 493, 292, 548, 491, 490, 551, 203, 0, 235, 139, + 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, + 541, 471, 480, 120, 478, 213, 191, 252, 514, 193, + 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, + 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, + 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, + 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, + 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, + 153, 129, 141, 201, 161, 202, 142, 174, 173, 175, + 0, 450, 0, 232, 255, 274, 114, 466, 239, 266, + 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, + 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, + 190, 214, 118, 254, 230, 462, 465, 460, 461, 509, + 510, 556, 557, 558, 534, 456, 0, 463, 464, 0, + 539, 546, 547, 513, 97, 106, 157, 271, 206, 131, + 256, 446, 459, 124, 469, 0, 0, 482, 487, 488, + 500, 502, 503, 504, 505, 512, 519, 520, 522, 528, + 529, 530, 531, 536, 543, 562, 99, 100, 107, 113, + 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, + 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, + 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, + 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, + 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, + 260, 263, 138, 250, 264, 550, 538, 0, 0, 495, + 553, 468, 485, 561, 486, 489, 526, 453, 508, 184, + 483, 0, 472, 448, 479, 449, 470, 497, 126, 501, + 467, 540, 511, 552, 155, 0, 473, 559, 158, 517, + 0, 231, 172, 0, 0, 0, 499, 542, 506, 535, + 494, 527, 458, 516, 554, 484, 524, 555, 0, 0, + 0, 94, 95, 96, 0, 0, 0, 0, 0, 0, + 0, 0, 116, 0, 521, 549, 481, 523, 525, 563, + 447, 518, 0, 451, 454, 560, 545, 476, 477, 0, + 0, 0, 0, 0, 0, 0, 498, 507, 532, 492, + 0, 0, 0, 0, 0, 0, 0, 0, 474, 0, + 515, 0, 0, 0, 455, 452, 0, 0, 0, 0, + 496, 0, 0, 0, 457, 0, 475, 533, 0, 445, + 135, 537, 544, 493, 292, 548, 491, 490, 551, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, - 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, - 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, + 181, 211, 215, 541, 471, 480, 120, 478, 213, 191, + 252, 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, - 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, - 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, + 174, 173, 175, 0, 450, 0, 232, 255, 274, 114, + 466, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, - 160, 208, 272, 190, 214, 118, 254, 230, 385, 396, - 391, 392, 389, 390, 388, 387, 386, 399, 377, 378, - 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, - 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, + 160, 208, 272, 190, 214, 118, 254, 230, 462, 465, + 460, 461, 509, 510, 556, 557, 558, 534, 456, 0, + 463, 464, 0, 539, 546, 547, 513, 97, 106, 157, + 271, 206, 131, 256, 446, 459, 124, 469, 0, 0, + 482, 487, 488, 500, 502, 503, 504, 505, 512, 519, + 520, 522, 528, 529, 530, 531, 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, - 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, - 0, 0, 0, 341, 0, 0, 0, 126, 0, 340, - 0, 0, 0, 155, 0, 0, 384, 158, 0, 0, - 231, 172, 0, 0, 0, 0, 0, 375, 376, 0, - 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, - 94, 95, 96, 362, 361, 364, 365, 366, 367, 0, - 0, 116, 363, 368, 369, 370, 0, 0, 0, 0, - 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 352, 353, 0, 0, 0, 0, 398, - 0, 354, 0, 0, 347, 348, 350, 349, 351, 356, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, - 397, 0, 0, 292, 0, 0, 395, 0, 203, 0, + 242, 243, 253, 260, 263, 138, 250, 264, 550, 538, + 0, 0, 495, 553, 468, 485, 561, 486, 489, 526, + 453, 508, 184, 483, 0, 472, 448, 479, 449, 470, + 497, 126, 501, 467, 540, 511, 552, 155, 0, 473, + 559, 158, 517, 0, 231, 172, 0, 0, 0, 499, + 542, 506, 535, 494, 527, 458, 516, 554, 484, 524, + 555, 0, 0, 0, 94, 95, 96, 0, 0, 0, + 0, 0, 0, 0, 0, 116, 0, 521, 549, 481, + 523, 525, 563, 447, 518, 0, 451, 454, 560, 545, + 476, 477, 0, 0, 0, 0, 0, 0, 0, 498, + 507, 532, 492, 0, 0, 0, 0, 0, 0, 0, + 0, 474, 0, 515, 0, 0, 0, 455, 452, 0, + 0, 0, 0, 496, 0, 0, 0, 457, 0, 475, + 533, 0, 445, 135, 537, 544, 493, 292, 548, 491, + 490, 551, 203, 0, 235, 139, 154, 112, 151, 98, + 108, 0, 137, 181, 211, 215, 541, 471, 480, 120, + 478, 213, 191, 252, 514, 193, 212, 159, 241, 204, + 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, + 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, + 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, + 121, 273, 109, 258, 105, 443, 257, 177, 240, 248, + 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, + 161, 202, 142, 174, 173, 175, 0, 450, 0, 232, + 255, 274, 114, 466, 239, 266, 269, 0, 205, 115, + 134, 128, 200, 132, 156, 265, 267, 268, 444, 442, + 437, 436, 152, 160, 208, 272, 190, 214, 118, 254, + 230, 462, 465, 460, 461, 509, 510, 556, 557, 558, + 534, 456, 0, 463, 464, 0, 539, 546, 547, 513, + 97, 106, 157, 271, 206, 131, 256, 446, 459, 124, + 469, 0, 0, 482, 487, 488, 500, 502, 503, 504, + 505, 512, 519, 520, 522, 528, 529, 530, 531, 536, + 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, + 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, + 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, + 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, + 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, + 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, + 264, 550, 538, 0, 0, 495, 553, 468, 485, 561, + 486, 489, 526, 453, 508, 184, 483, 0, 472, 448, + 479, 449, 470, 497, 126, 501, 467, 540, 511, 552, + 155, 0, 473, 559, 158, 517, 0, 231, 172, 0, + 0, 0, 499, 542, 506, 535, 494, 527, 458, 516, + 554, 484, 524, 555, 0, 0, 0, 94, 95, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 116, 0, + 521, 549, 481, 523, 525, 563, 447, 518, 0, 451, + 454, 560, 545, 476, 477, 0, 0, 0, 0, 0, + 0, 0, 498, 507, 532, 492, 0, 0, 0, 0, + 0, 0, 0, 0, 474, 0, 515, 0, 0, 0, + 455, 452, 0, 0, 0, 0, 496, 0, 0, 0, + 457, 0, 475, 533, 0, 445, 135, 537, 544, 493, + 292, 548, 491, 490, 551, 203, 0, 235, 139, 154, + 112, 151, 98, 108, 0, 137, 181, 211, 215, 541, + 471, 480, 120, 478, 213, 191, 252, 514, 193, 212, + 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, + 101, 237, 777, 117, 223, 0, 0, 0, 103, 247, + 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, + 183, 244, 245, 121, 273, 109, 258, 105, 443, 257, + 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, + 129, 141, 201, 161, 202, 142, 174, 173, 175, 0, + 450, 0, 232, 255, 274, 114, 466, 239, 266, 269, + 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, + 268, 444, 442, 437, 436, 152, 160, 208, 272, 190, + 214, 118, 254, 230, 462, 465, 460, 461, 509, 510, + 556, 557, 558, 534, 456, 0, 463, 464, 0, 539, + 546, 547, 513, 97, 106, 157, 271, 206, 131, 256, + 446, 459, 124, 469, 0, 0, 482, 487, 488, 500, + 502, 503, 504, 505, 512, 519, 520, 522, 528, 529, + 530, 531, 536, 543, 562, 99, 100, 107, 113, 119, + 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, + 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, + 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, + 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, + 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, + 263, 138, 250, 264, 550, 538, 0, 0, 495, 553, + 468, 485, 561, 486, 489, 526, 453, 508, 184, 483, + 0, 472, 448, 479, 449, 470, 497, 126, 501, 467, + 540, 511, 552, 155, 0, 473, 559, 158, 517, 0, + 231, 172, 0, 0, 0, 499, 542, 506, 535, 494, + 527, 458, 516, 554, 484, 524, 555, 0, 0, 0, + 94, 95, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 116, 0, 521, 549, 481, 523, 525, 563, 447, + 518, 0, 451, 454, 560, 545, 476, 477, 0, 0, + 0, 0, 0, 0, 0, 498, 507, 532, 492, 0, + 0, 0, 0, 0, 0, 0, 0, 474, 0, 515, + 0, 0, 0, 455, 452, 0, 0, 0, 0, 496, + 0, 0, 0, 457, 0, 475, 533, 0, 445, 135, + 537, 544, 493, 292, 548, 491, 490, 551, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, - 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, - 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, - 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, + 211, 215, 541, 471, 480, 120, 478, 213, 191, 252, + 514, 193, 212, 159, 241, 204, 251, 261, 262, 238, + 259, 270, 228, 101, 237, 434, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, - 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, + 105, 443, 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, - 173, 175, 0, 0, 0, 232, 255, 274, 114, 0, + 173, 175, 0, 450, 0, 232, 255, 274, 114, 466, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, - 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, - 208, 272, 190, 214, 118, 254, 230, 385, 396, 391, - 392, 389, 390, 388, 387, 386, 399, 377, 378, 379, - 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, - 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, + 156, 265, 267, 268, 444, 442, 437, 436, 152, 160, + 208, 272, 190, 214, 118, 254, 230, 462, 465, 460, + 461, 509, 510, 556, 557, 558, 534, 456, 0, 463, + 464, 0, 539, 546, 547, 513, 97, 106, 157, 271, + 206, 131, 256, 446, 459, 124, 469, 0, 0, 482, + 487, 488, 500, 502, 503, 504, 505, 512, 519, 520, + 522, 528, 529, 530, 531, 536, 543, 562, 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, - 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, - 0, 0, 155, 0, 0, 384, 158, 0, 0, 231, + 941, 0, 341, 0, 0, 0, 126, 0, 340, 0, + 0, 0, 155, 0, 942, 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 94, 95, 96, 362, 361, 364, 365, 366, 367, 0, 0, - 116, 363, 368, 369, 370, 0, 0, 0, 0, 0, + 116, 363, 368, 369, 370, 0, 0, 0, 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 352, 353, 0, 0, 0, 0, 398, 0, + 0, 0, 352, 353, 424, 0, 0, 0, 398, 0, 354, 0, 0, 347, 348, 350, 349, 351, 356, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, 397, 0, 0, 292, 0, 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, - 215, 0, 0, 0, 120, 0, 213, 191, 252, 1620, + 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, @@ -1952,12 +1724,12 @@ var yyAct = [...]int{ 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, - 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, + 0, 341, 0, 0, 0, 126, 0, 340, 0, 0, 0, 155, 0, 0, 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 375, 376, 0, 0, 0, - 0, 0, 0, 0, 0, 59, 0, 412, 94, 95, + 0, 0, 0, 1046, 0, 59, 0, 0, 94, 95, 96, 362, 361, 364, 365, 366, 367, 0, 0, 116, - 363, 368, 369, 370, 0, 0, 0, 0, 0, 355, + 363, 368, 369, 370, 1047, 0, 0, 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 353, 0, 0, 0, 0, 398, 0, 354, @@ -1987,12 +1759,12 @@ var yyAct = [...]int{ 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, 0, - 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, + 341, 0, 0, 0, 126, 0, 340, 0, 0, 0, 155, 0, 0, 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 375, 376, 0, 0, 0, 0, - 0, 0, 0, 0, 59, 0, 0, 94, 95, 96, + 0, 0, 0, 0, 59, 0, 412, 94, 95, 96, 362, 361, 364, 365, 366, 367, 0, 0, 116, 363, - 368, 369, 370, 0, 0, 0, 0, 0, 355, 0, + 368, 369, 370, 0, 0, 0, 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, 353, 0, 0, 0, 0, 398, 0, 354, 0, @@ -2021,19 +1793,19 @@ var yyAct = [...]int{ 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, - 263, 138, 250, 264, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, - 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 0, - 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 657, 656, 666, 667, 659, - 660, 661, 662, 663, 664, 665, 658, 0, 0, 668, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 135, 0, 0, 0, 292, - 0, 0, 0, 0, 203, 0, 235, 139, 154, 112, + 263, 138, 250, 264, 184, 0, 0, 0, 0, 341, + 0, 0, 0, 126, 0, 340, 0, 0, 0, 155, + 0, 0, 384, 158, 0, 0, 231, 172, 0, 0, + 0, 0, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 0, 59, 0, 0, 94, 95, 96, 362, + 361, 364, 365, 366, 367, 0, 0, 116, 363, 368, + 369, 370, 0, 0, 0, 0, 338, 355, 0, 383, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 353, 424, 0, 0, 0, 398, 0, 354, 0, 0, + 347, 348, 350, 349, 351, 356, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 135, 397, 0, 0, 292, + 0, 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, @@ -2045,9 +1817,9 @@ var yyAct = [...]int{ 0, 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, - 118, 254, 230, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 97, 106, 157, 271, 206, 131, 256, 0, + 118, 254, 230, 385, 396, 391, 392, 389, 390, 388, + 387, 386, 399, 377, 378, 379, 380, 382, 0, 393, + 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, @@ -2056,19 +1828,19 @@ var yyAct = [...]int{ 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, - 138, 250, 264, 184, 0, 0, 0, 752, 0, 0, - 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, - 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 94, 95, 96, 0, 754, - 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, - 0, 0, 646, 647, 645, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 648, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 135, 0, 0, 0, 292, 0, - 0, 0, 0, 203, 0, 235, 139, 154, 112, 151, + 138, 250, 264, 184, 0, 0, 0, 0, 341, 0, + 0, 0, 126, 0, 340, 0, 0, 0, 155, 0, + 0, 384, 158, 0, 0, 231, 172, 0, 0, 0, + 0, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 0, 0, 94, 95, 96, 362, 959, + 364, 365, 366, 367, 0, 0, 116, 363, 368, 369, + 370, 0, 0, 0, 0, 338, 355, 0, 383, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 353, + 424, 0, 0, 0, 398, 0, 354, 0, 0, 347, + 348, 350, 349, 351, 356, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 397, 0, 0, 292, 0, + 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, @@ -2080,9 +1852,9 @@ var yyAct = [...]int{ 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, - 254, 230, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 97, 106, 157, 271, 206, 131, 256, 0, 0, + 254, 230, 385, 396, 391, 392, 389, 390, 388, 387, + 386, 399, 377, 378, 379, 380, 382, 0, 393, 394, + 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, 127, @@ -2091,19 +1863,19 @@ var yyAct = [...]int{ 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, - 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, - 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, - 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 0, 0, 0, - 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, - 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 250, 264, 184, 0, 0, 0, 0, 341, 0, 0, + 0, 126, 0, 340, 0, 0, 0, 155, 0, 0, + 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 94, 95, 96, 362, 956, 364, + 365, 366, 367, 0, 0, 116, 363, 368, 369, 370, + 0, 0, 0, 0, 338, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 135, 88, 89, 0, 85, 0, 0, - 0, 90, 203, 0, 235, 139, 154, 112, 151, 98, + 0, 0, 0, 0, 0, 0, 0, 352, 353, 424, + 0, 0, 0, 398, 0, 354, 0, 0, 347, 348, + 350, 349, 351, 356, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 135, 397, 0, 0, 292, 0, 0, + 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, @@ -2115,8 +1887,8 @@ var yyAct = [...]int{ 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, - 230, 0, 87, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230, 385, 396, 391, 392, 389, 390, 388, 387, 386, + 399, 377, 378, 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2126,55 +1898,55 @@ var yyAct = [...]int{ 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, - 264, 184, 0, 0, 0, 1025, 0, 0, 0, 0, - 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, - 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 0, 1027, 0, 0, - 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 135, 0, 0, 0, 292, 0, 0, 0, - 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, - 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, - 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, - 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, - 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, - 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, - 273, 109, 258, 105, 110, 257, 177, 240, 248, 171, - 164, 104, 246, 169, 163, 153, 129, 141, 201, 161, - 202, 142, 174, 173, 175, 0, 0, 0, 232, 255, - 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, - 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, - 229, 152, 160, 208, 272, 190, 214, 118, 254, 230, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, - 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 99, 100, 107, 113, 119, 123, 127, 130, 136, - 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, - 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, - 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, - 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, - 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, - 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, - 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, - 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 59, 0, 0, 94, 95, 96, 0, 0, - 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 264, 405, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 184, 0, 0, 0, 0, 341, + 0, 0, 0, 126, 0, 340, 0, 0, 0, 155, + 0, 0, 384, 158, 0, 0, 231, 172, 0, 0, + 0, 0, 0, 375, 376, 0, 0, 0, 0, 0, + 0, 0, 0, 59, 0, 0, 94, 95, 96, 362, + 361, 364, 365, 366, 367, 0, 0, 116, 363, 368, + 369, 370, 0, 0, 0, 0, 338, 355, 0, 383, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 352, + 353, 0, 0, 0, 0, 398, 0, 354, 0, 0, + 347, 348, 350, 349, 351, 356, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 135, 397, 0, 0, 292, + 0, 0, 395, 0, 203, 0, 235, 139, 154, 112, + 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, + 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, + 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, + 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, + 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, + 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, + 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, + 141, 201, 161, 202, 142, 174, 173, 175, 0, 0, + 0, 232, 255, 274, 114, 0, 239, 266, 269, 0, + 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, + 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, + 118, 254, 230, 385, 396, 391, 392, 389, 390, 388, + 387, 386, 399, 377, 378, 379, 380, 382, 0, 393, + 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, + 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 135, 0, 0, 0, 292, 0, - 0, 0, 0, 203, 0, 235, 139, 154, 112, 151, + 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, + 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, + 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, + 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, + 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, + 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, + 138, 250, 264, 184, 0, 0, 0, 0, 341, 0, + 0, 0, 126, 0, 340, 0, 0, 0, 155, 0, + 0, 384, 158, 0, 0, 231, 172, 0, 0, 0, + 0, 0, 375, 376, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 0, 0, 94, 95, 96, 362, 361, + 364, 365, 366, 367, 0, 0, 116, 363, 368, 369, + 370, 0, 0, 0, 0, 338, 355, 0, 383, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 352, 353, + 0, 0, 0, 0, 398, 0, 354, 0, 0, 347, + 348, 350, 349, 351, 356, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 397, 0, 0, 292, 0, + 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, @@ -2186,9 +1958,9 @@ var yyAct = [...]int{ 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, - 254, 230, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 97, 106, 157, 271, 206, 131, 256, 0, 0, + 254, 230, 385, 396, 391, 392, 389, 390, 388, 387, + 386, 399, 377, 378, 379, 380, 382, 0, 393, 394, + 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, 127, @@ -2197,21 +1969,21 @@ var yyAct = [...]int{ 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, - 250, 264, 184, 0, 0, 0, 1025, 0, 0, 0, + 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, - 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 0, 1027, 0, - 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, + 0, 375, 376, 0, 0, 0, 0, 0, 0, 0, + 0, 59, 0, 0, 94, 95, 96, 362, 361, 364, + 365, 366, 367, 0, 0, 116, 363, 368, 369, 370, + 0, 0, 0, 0, 0, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 135, 0, 0, 0, 292, 0, 0, - 0, 0, 203, 0, 235, 139, 154, 112, 151, 98, + 0, 0, 0, 0, 0, 0, 0, 352, 353, 0, + 0, 0, 0, 398, 0, 354, 0, 0, 347, 348, + 350, 349, 351, 356, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 135, 397, 0, 0, 292, 0, 0, + 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, - 0, 213, 191, 252, 0, 1023, 212, 159, 241, 204, + 0, 213, 191, 252, 1623, 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, @@ -2221,8 +1993,8 @@ var yyAct = [...]int{ 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230, 385, 396, 391, 392, 389, 390, 388, 387, 386, + 399, 377, 378, 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2233,17 +2005,17 @@ var yyAct = [...]int{ 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, 0, - 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, + 126, 0, 0, 0, 0, 0, 155, 0, 0, 384, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, + 375, 376, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 0, 412, 94, 95, 96, 362, 361, 364, 365, + 366, 367, 0, 0, 116, 363, 368, 369, 370, 0, + 0, 0, 0, 0, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 0, 0, 990, 0, - 0, 991, 0, 0, 116, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 135, 0, 0, 0, 292, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 352, 353, 0, 0, + 0, 0, 398, 0, 354, 0, 0, 347, 348, 350, + 349, 351, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 135, 397, 0, 0, 292, 0, 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, @@ -2256,8 +2028,8 @@ var yyAct = [...]int{ 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, 230, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, + 385, 396, 391, 392, 389, 390, 388, 387, 386, 399, + 377, 378, 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2268,17 +2040,17 @@ var yyAct = [...]int{ 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, - 0, 786, 0, 0, 0, 155, 0, 0, 0, 158, - 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 0, 785, 0, 0, 0, - 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 155, 0, 0, 384, 158, + 0, 0, 231, 172, 0, 0, 0, 0, 0, 375, + 376, 0, 0, 0, 0, 0, 0, 0, 0, 59, + 0, 0, 94, 95, 96, 362, 361, 364, 365, 366, + 367, 0, 0, 116, 363, 368, 369, 370, 0, 0, + 0, 0, 0, 355, 0, 383, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 135, 0, 0, 0, 292, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 352, 353, 0, 0, 0, + 0, 398, 0, 354, 0, 0, 347, 348, 350, 349, + 351, 356, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 135, 397, 0, 0, 292, 0, 0, 395, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, @@ -2290,9 +2062,9 @@ var yyAct = [...]int{ 142, 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, - 152, 160, 208, 272, 190, 214, 118, 254, 230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 97, 106, + 152, 160, 208, 272, 190, 214, 118, 254, 230, 385, + 396, 391, 392, 389, 390, 388, 387, 386, 399, 377, + 378, 379, 380, 382, 0, 393, 394, 381, 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2306,37 +2078,143 @@ var yyAct = [...]int{ 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 412, 94, 95, 96, 0, 0, 0, 0, 0, 0, - 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 94, 95, 96, 0, 0, 0, 0, 0, 0, + 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 659, 658, 668, 669, 661, 662, 663, 664, 665, 666, + 667, 660, 0, 0, 670, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 135, 0, 0, 0, 292, 0, 0, 0, 0, 203, + 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, + 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, + 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, + 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, + 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, + 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, + 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, + 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, + 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, + 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, + 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, + 160, 208, 272, 190, 214, 118, 254, 230, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 97, 106, 157, + 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, + 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, + 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, + 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, + 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, + 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, + 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, + 0, 0, 754, 0, 0, 0, 0, 126, 0, 0, + 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, + 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 0, 756, 0, 0, 0, 0, 0, + 0, 116, 0, 0, 0, 0, 0, 648, 649, 647, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 650, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, + 0, 0, 0, 292, 0, 0, 0, 0, 203, 0, + 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, + 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, + 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, + 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, + 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, + 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, + 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, + 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, + 173, 175, 0, 0, 0, 232, 255, 274, 114, 0, + 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, + 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, + 208, 272, 190, 214, 118, 254, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 97, 106, 157, 271, + 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, + 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, + 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, + 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, + 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, + 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, + 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, + 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, + 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, + 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, + 116, 0, 0, 0, 0, 0, 86, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 135, 88, + 89, 0, 85, 0, 0, 0, 90, 203, 0, 235, + 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, + 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, + 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, + 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, + 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, + 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, + 110, 257, 177, 240, 248, 171, 164, 104, 246, 169, + 163, 153, 129, 141, 201, 161, 202, 142, 174, 173, + 175, 0, 0, 0, 232, 255, 274, 114, 0, 239, + 266, 269, 0, 205, 115, 134, 128, 200, 132, 156, + 265, 267, 268, 176, 111, 144, 229, 152, 160, 208, + 272, 190, 214, 118, 254, 230, 0, 87, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 97, 106, 157, 271, 206, + 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 99, 100, 107, + 113, 119, 123, 127, 130, 136, 140, 143, 145, 146, + 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, + 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, + 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, + 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, + 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, + 1028, 0, 0, 0, 0, 126, 0, 0, 0, 0, + 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, + 96, 0, 1030, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 135, 0, 0, 0, 292, 0, 0, 0, 0, 203, - 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, - 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, - 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, - 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, - 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, - 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, - 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, - 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, - 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, - 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, - 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, - 160, 208, 272, 190, 214, 118, 254, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 97, 106, 157, - 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, - 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, - 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, - 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, - 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, - 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, + 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, + 0, 292, 0, 0, 0, 0, 203, 0, 235, 139, + 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, + 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, + 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, + 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, + 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, + 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, + 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, + 153, 129, 141, 201, 161, 202, 142, 174, 173, 175, + 0, 0, 0, 232, 255, 274, 114, 0, 239, 266, + 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, + 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, + 190, 214, 118, 254, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 97, 106, 157, 271, 206, 131, + 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 100, 107, 113, + 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, + 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, + 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, + 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, + 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, + 260, 263, 138, 250, 264, 30, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2372,11 +2250,11 @@ var yyAct = [...]int{ 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, - 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, + 0, 1028, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 0, 1027, 0, 0, 0, 0, 0, 0, + 95, 96, 0, 1030, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2386,7 +2264,7 @@ var yyAct = [...]int{ 0, 0, 292, 0, 0, 0, 0, 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, 0, - 193, 212, 159, 241, 204, 251, 261, 262, 238, 259, + 1026, 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, 105, @@ -2411,7 +2289,7 @@ var yyAct = [...]int{ 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 0, 754, 0, 0, 0, 0, 0, 0, 116, + 96, 0, 0, 993, 0, 0, 994, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2441,12 +2319,116 @@ var yyAct = [...]int{ 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, - 260, 263, 138, 250, 264, 768, 0, 0, 0, 0, - 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, + 260, 263, 138, 250, 264, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 126, 0, 788, 0, 0, 0, + 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, + 0, 787, 0, 0, 0, 0, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, + 292, 0, 0, 0, 0, 203, 0, 235, 139, 154, + 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, + 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, + 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, + 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, + 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, + 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, + 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, + 129, 141, 201, 161, 202, 142, 174, 173, 175, 0, + 0, 0, 232, 255, 274, 114, 0, 239, 266, 269, + 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, + 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, + 214, 118, 254, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 97, 106, 157, 271, 206, 131, 256, + 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 99, 100, 107, 113, 119, + 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, + 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, + 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, + 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, + 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, + 263, 138, 250, 264, 184, 0, 0, 0, 0, 0, + 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, + 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 412, 94, 95, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 135, 0, 0, 0, 292, + 0, 0, 0, 0, 203, 0, 235, 139, 154, 112, + 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, + 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, + 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, + 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, + 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, + 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, + 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, + 141, 201, 161, 202, 142, 174, 173, 175, 0, 0, + 0, 232, 255, 274, 114, 0, 239, 266, 269, 0, + 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, + 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, + 118, 254, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 97, 106, 157, 271, 206, 131, 256, 0, + 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, + 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, + 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, + 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, + 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, + 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, + 138, 250, 264, 184, 0, 0, 0, 0, 0, 0, + 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, + 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 59, 0, 0, 94, 95, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 0, 0, 0, 292, 0, + 0, 0, 0, 203, 0, 235, 139, 154, 112, 151, + 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, + 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, + 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, + 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, + 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, + 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, + 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, + 201, 161, 202, 142, 174, 173, 175, 0, 0, 0, + 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, + 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, + 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, + 254, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 97, 106, 157, 271, 206, 131, 256, 0, 0, + 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 99, 100, 107, 113, 119, 123, 127, + 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, + 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, + 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, + 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, + 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, + 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 0, 1030, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2477,11 +2459,11 @@ var yyAct = [...]int{ 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, - 264, 184, 0, 0, 0, 0, 0, 0, 0, 758, + 264, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 0, 0, 0, 0, + 0, 0, 0, 94, 95, 96, 0, 756, 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2510,113 +2492,9 @@ var yyAct = [...]int{ 140, 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, - 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, - 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, - 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, - 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, - 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 0, 635, 0, 0, 0, - 0, 0, 0, 116, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 135, 0, 0, 0, 292, 0, 0, 0, 0, - 203, 0, 235, 139, 154, 112, 151, 98, 108, 0, - 137, 181, 211, 215, 0, 0, 0, 120, 0, 213, - 191, 252, 0, 193, 212, 159, 241, 204, 251, 261, - 262, 238, 259, 270, 228, 101, 237, 249, 117, 223, - 0, 0, 0, 103, 247, 234, 170, 148, 149, 102, - 0, 209, 125, 133, 122, 183, 244, 245, 121, 273, - 109, 258, 105, 110, 257, 177, 240, 248, 171, 164, - 104, 246, 169, 163, 153, 129, 141, 201, 161, 202, - 142, 174, 173, 175, 0, 0, 0, 232, 255, 274, - 114, 0, 239, 266, 269, 0, 205, 115, 134, 128, - 200, 132, 156, 265, 267, 268, 176, 111, 144, 229, - 152, 160, 208, 272, 190, 214, 118, 254, 230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 97, 106, - 157, 271, 206, 131, 256, 0, 0, 124, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 99, 100, 107, 113, 119, 123, 127, 130, 136, 140, - 143, 145, 146, 147, 150, 162, 165, 166, 167, 168, - 178, 179, 180, 182, 185, 186, 187, 188, 189, 192, - 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, - 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, - 236, 242, 243, 253, 260, 263, 138, 250, 264, 184, - 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, - 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, - 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 0, 0, 0, 0, 0, 0, - 0, 0, 116, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 329, 0, - 135, 0, 0, 0, 292, 0, 0, 0, 0, 203, - 0, 235, 139, 154, 112, 151, 98, 108, 0, 137, - 181, 211, 215, 0, 0, 0, 120, 0, 213, 191, - 252, 0, 193, 212, 159, 241, 204, 251, 261, 262, - 238, 259, 270, 228, 101, 237, 249, 117, 223, 0, - 0, 0, 103, 247, 234, 170, 148, 149, 102, 0, - 209, 125, 133, 122, 183, 244, 245, 121, 273, 109, - 258, 105, 110, 257, 177, 240, 248, 171, 164, 104, - 246, 169, 163, 153, 129, 141, 201, 161, 202, 142, - 174, 173, 175, 0, 0, 0, 232, 255, 274, 114, - 0, 239, 266, 269, 0, 205, 115, 134, 128, 200, - 132, 156, 265, 267, 268, 176, 111, 144, 229, 152, - 160, 208, 272, 190, 214, 118, 254, 230, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 97, 106, 157, - 271, 206, 131, 256, 0, 0, 124, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 100, 107, 113, 119, 123, 127, 130, 136, 140, 143, - 145, 146, 147, 150, 162, 165, 166, 167, 168, 178, - 179, 180, 182, 185, 186, 187, 188, 189, 192, 194, - 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, - 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, - 242, 243, 253, 260, 263, 328, 250, 264, 184, 0, - 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, - 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, - 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 0, 0, 0, 0, 0, 0, 0, - 0, 116, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, - 0, 287, 0, 292, 0, 0, 0, 0, 203, 0, - 235, 139, 154, 112, 151, 98, 108, 0, 137, 181, - 211, 215, 0, 0, 0, 120, 0, 213, 191, 252, - 0, 193, 212, 159, 241, 204, 251, 261, 262, 238, - 259, 270, 228, 101, 237, 249, 117, 223, 0, 0, - 0, 103, 247, 234, 170, 148, 149, 102, 0, 209, - 125, 133, 122, 183, 244, 245, 121, 273, 109, 258, - 105, 110, 257, 177, 240, 248, 171, 164, 104, 246, - 169, 163, 153, 129, 141, 201, 161, 202, 142, 174, - 173, 175, 0, 0, 0, 232, 255, 274, 114, 0, - 239, 266, 269, 0, 205, 115, 134, 128, 200, 132, - 156, 265, 267, 268, 176, 111, 144, 229, 152, 160, - 208, 272, 190, 214, 118, 254, 230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 97, 106, 157, 271, - 206, 131, 256, 0, 0, 124, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 99, 100, - 107, 113, 119, 123, 127, 130, 136, 140, 143, 145, - 146, 147, 150, 162, 165, 166, 167, 168, 178, 179, - 180, 182, 185, 186, 187, 188, 189, 192, 194, 195, - 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, - 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, - 243, 253, 260, 263, 138, 250, 264, 184, 0, 0, + 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, + 233, 236, 242, 243, 253, 260, 263, 138, 250, 264, + 770, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2651,19 +2529,194 @@ var yyAct = [...]int{ 182, 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, 227, 233, 236, 242, 243, - 253, 260, 263, 138, 250, 264, + 253, 260, 263, 138, 250, 264, 184, 0, 0, 0, + 0, 0, 0, 0, 760, 126, 0, 0, 0, 0, + 0, 155, 0, 0, 0, 158, 0, 0, 231, 172, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, + 96, 0, 0, 0, 0, 0, 0, 0, 0, 116, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, + 0, 292, 0, 0, 0, 0, 203, 0, 235, 139, + 154, 112, 151, 98, 108, 0, 137, 181, 211, 215, + 0, 0, 0, 120, 0, 213, 191, 252, 0, 193, + 212, 159, 241, 204, 251, 261, 262, 238, 259, 270, + 228, 101, 237, 249, 117, 223, 0, 0, 0, 103, + 247, 234, 170, 148, 149, 102, 0, 209, 125, 133, + 122, 183, 244, 245, 121, 273, 109, 258, 105, 110, + 257, 177, 240, 248, 171, 164, 104, 246, 169, 163, + 153, 129, 141, 201, 161, 202, 142, 174, 173, 175, + 0, 0, 0, 232, 255, 274, 114, 0, 239, 266, + 269, 0, 205, 115, 134, 128, 200, 132, 156, 265, + 267, 268, 176, 111, 144, 229, 152, 160, 208, 272, + 190, 214, 118, 254, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 97, 106, 157, 271, 206, 131, + 256, 0, 0, 124, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 100, 107, 113, + 119, 123, 127, 130, 136, 140, 143, 145, 146, 147, + 150, 162, 165, 166, 167, 168, 178, 179, 180, 182, + 185, 186, 187, 188, 189, 192, 194, 195, 196, 197, + 198, 199, 207, 210, 216, 217, 218, 219, 220, 221, + 222, 224, 225, 226, 227, 233, 236, 242, 243, 253, + 260, 263, 138, 250, 264, 184, 0, 0, 0, 0, + 0, 0, 0, 0, 126, 0, 0, 0, 0, 0, + 155, 0, 0, 0, 158, 0, 0, 231, 172, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, + 0, 637, 0, 0, 0, 0, 0, 0, 116, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 135, 0, 0, 0, + 292, 0, 0, 0, 0, 203, 0, 235, 139, 154, + 112, 151, 98, 108, 0, 137, 181, 211, 215, 0, + 0, 0, 120, 0, 213, 191, 252, 0, 193, 212, + 159, 241, 204, 251, 261, 262, 238, 259, 270, 228, + 101, 237, 249, 117, 223, 0, 0, 0, 103, 247, + 234, 170, 148, 149, 102, 0, 209, 125, 133, 122, + 183, 244, 245, 121, 273, 109, 258, 105, 110, 257, + 177, 240, 248, 171, 164, 104, 246, 169, 163, 153, + 129, 141, 201, 161, 202, 142, 174, 173, 175, 0, + 0, 0, 232, 255, 274, 114, 0, 239, 266, 269, + 0, 205, 115, 134, 128, 200, 132, 156, 265, 267, + 268, 176, 111, 144, 229, 152, 160, 208, 272, 190, + 214, 118, 254, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 97, 106, 157, 271, 206, 131, 256, + 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 99, 100, 107, 113, 119, + 123, 127, 130, 136, 140, 143, 145, 146, 147, 150, + 162, 165, 166, 167, 168, 178, 179, 180, 182, 185, + 186, 187, 188, 189, 192, 194, 195, 196, 197, 198, + 199, 207, 210, 216, 217, 218, 219, 220, 221, 222, + 224, 225, 226, 227, 233, 236, 242, 243, 253, 260, + 263, 138, 250, 264, 184, 0, 0, 0, 0, 0, + 0, 0, 0, 126, 0, 0, 0, 0, 0, 155, + 0, 0, 0, 158, 0, 0, 231, 172, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 94, 95, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 116, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 329, 0, 135, 0, 0, 0, 292, + 0, 0, 0, 0, 203, 0, 235, 139, 154, 112, + 151, 98, 108, 0, 137, 181, 211, 215, 0, 0, + 0, 120, 0, 213, 191, 252, 0, 193, 212, 159, + 241, 204, 251, 261, 262, 238, 259, 270, 228, 101, + 237, 249, 117, 223, 0, 0, 0, 103, 247, 234, + 170, 148, 149, 102, 0, 209, 125, 133, 122, 183, + 244, 245, 121, 273, 109, 258, 105, 110, 257, 177, + 240, 248, 171, 164, 104, 246, 169, 163, 153, 129, + 141, 201, 161, 202, 142, 174, 173, 175, 0, 0, + 0, 232, 255, 274, 114, 0, 239, 266, 269, 0, + 205, 115, 134, 128, 200, 132, 156, 265, 267, 268, + 176, 111, 144, 229, 152, 160, 208, 272, 190, 214, + 118, 254, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 97, 106, 157, 271, 206, 131, 256, 0, + 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 99, 100, 107, 113, 119, 123, + 127, 130, 136, 140, 143, 145, 146, 147, 150, 162, + 165, 166, 167, 168, 178, 179, 180, 182, 185, 186, + 187, 188, 189, 192, 194, 195, 196, 197, 198, 199, + 207, 210, 216, 217, 218, 219, 220, 221, 222, 224, + 225, 226, 227, 233, 236, 242, 243, 253, 260, 263, + 328, 250, 264, 184, 0, 0, 0, 0, 0, 0, + 0, 0, 126, 0, 0, 0, 0, 0, 155, 0, + 0, 0, 158, 0, 0, 231, 172, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 116, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 135, 0, 287, 0, 292, 0, + 0, 0, 0, 203, 0, 235, 139, 154, 112, 151, + 98, 108, 0, 137, 181, 211, 215, 0, 0, 0, + 120, 0, 213, 191, 252, 0, 193, 212, 159, 241, + 204, 251, 261, 262, 238, 259, 270, 228, 101, 237, + 249, 117, 223, 0, 0, 0, 103, 247, 234, 170, + 148, 149, 102, 0, 209, 125, 133, 122, 183, 244, + 245, 121, 273, 109, 258, 105, 110, 257, 177, 240, + 248, 171, 164, 104, 246, 169, 163, 153, 129, 141, + 201, 161, 202, 142, 174, 173, 175, 0, 0, 0, + 232, 255, 274, 114, 0, 239, 266, 269, 0, 205, + 115, 134, 128, 200, 132, 156, 265, 267, 268, 176, + 111, 144, 229, 152, 160, 208, 272, 190, 214, 118, + 254, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 97, 106, 157, 271, 206, 131, 256, 0, 0, + 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 99, 100, 107, 113, 119, 123, 127, + 130, 136, 140, 143, 145, 146, 147, 150, 162, 165, + 166, 167, 168, 178, 179, 180, 182, 185, 186, 187, + 188, 189, 192, 194, 195, 196, 197, 198, 199, 207, + 210, 216, 217, 218, 219, 220, 221, 222, 224, 225, + 226, 227, 233, 236, 242, 243, 253, 260, 263, 138, + 250, 264, 184, 0, 0, 0, 0, 0, 0, 0, + 0, 126, 0, 0, 0, 0, 0, 155, 0, 0, + 0, 158, 0, 0, 231, 172, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 0, 0, 0, + 0, 0, 0, 0, 0, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 135, 0, 0, 0, 292, 0, 0, + 0, 0, 203, 0, 235, 139, 154, 112, 151, 98, + 108, 0, 137, 181, 211, 215, 0, 0, 0, 120, + 0, 213, 191, 252, 0, 193, 212, 159, 241, 204, + 251, 261, 262, 238, 259, 270, 228, 101, 237, 249, + 117, 223, 0, 0, 0, 103, 247, 234, 170, 148, + 149, 102, 0, 209, 125, 133, 122, 183, 244, 245, + 121, 273, 109, 258, 105, 110, 257, 177, 240, 248, + 171, 164, 104, 246, 169, 163, 153, 129, 141, 201, + 161, 202, 142, 174, 173, 175, 0, 0, 0, 232, + 255, 274, 114, 0, 239, 266, 269, 0, 205, 115, + 134, 128, 200, 132, 156, 265, 267, 268, 176, 111, + 144, 229, 152, 160, 208, 272, 190, 214, 118, 254, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 97, 106, 157, 271, 206, 131, 256, 0, 0, 124, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 99, 100, 107, 113, 119, 123, 127, 130, + 136, 140, 143, 145, 146, 147, 150, 162, 165, 166, + 167, 168, 178, 179, 180, 182, 185, 186, 187, 188, + 189, 192, 194, 195, 196, 197, 198, 199, 207, 210, + 216, 217, 218, 219, 220, 221, 222, 224, 225, 226, + 227, 233, 236, 242, 243, 253, 260, 263, 138, 250, + 264, } var yyPact = [...]int{ - 93, -1000, -287, 1091, -1000, -1000, -1000, -1000, -1000, -1000, + 1714, -1000, -279, 1028, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1029, 880, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 294, 11773, 97, - 172, 0, 16679, 171, 1865, 17028, -1000, 22, -1000, -2, - 17028, 15, 16330, -1000, -1000, -92, -102, -1000, 9679, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 789, 1017, 1022, - 1027, 631, 1247, -1000, 8270, 8270, 133, 133, 133, 6874, - -1000, -1000, 476, 17028, 167, 17028, -155, 129, 129, 129, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 969, 806, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 342, 12288, -31, + 151, 34, 17194, 148, 2038, 17543, -1000, 31, -1000, 13, + 17543, 27, 16845, -1000, -1000, -85, -97, -1000, 10194, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 784, 956, 964, + 966, 665, 1000, -1000, 8785, 8785, 84, 84, 84, 7389, + -1000, -1000, 524, 17543, 124, 17543, -152, 102, 102, 102, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2682,24 +2735,24 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 169, 17028, 614, 614, 256, - -1000, 17028, 127, 614, 127, 127, 127, 17028, -1000, 210, - -1000, -1000, -1000, 17028, 614, 967, 348, 75, 261, 261, - 261, -1000, 224, -1000, 4333, 67, 4333, -60, 1045, 35, - -23, -1000, 348, 4333, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 150, -1000, -1000, 17028, 15981, 158, 311, -1000, - -1000, -1000, -1000, -1000, -1000, 582, 666, -1000, 9679, 1654, - 744, 744, -1000, -1000, 188, -1000, -1000, 10726, 10726, 10726, - 10726, 10726, 10726, 10726, 10726, 10726, 10726, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 141, 17543, 564, 564, 240, + 569, 17543, 93, 564, 93, 93, 93, 17543, -1000, 198, + -1000, -1000, -1000, 17543, 564, 903, 341, 69, 279, 279, + 279, -1000, 204, -1000, 4848, 40, 4848, -40, 987, 37, + -43, -1000, 341, 4848, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 106, -1000, -1000, 17543, 16496, 134, 334, -1000, + -1000, -1000, -1000, -1000, -1000, 644, 387, -1000, 10194, 2278, + 749, 749, -1000, -1000, 178, -1000, -1000, 11241, 11241, 11241, + 11241, 11241, 11241, 11241, 11241, 11241, 11241, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 744, 208, -1000, 9330, 744, 744, 744, 744, 744, - 744, 744, 744, 9679, 744, 744, 744, 744, 744, 744, - 744, 744, 744, 744, 744, 744, 744, 744, 744, 744, - -1000, -1000, 1029, -1000, 880, -1000, -1000, -1000, 982, 9679, - 9679, 1029, -1000, 950, 8270, -1000, -1000, 1057, -1000, -1000, - -1000, -1000, 352, 1068, -1000, 11424, 202, 1065, 15632, 14229, - 15283, 825, 6511, -128, -1000, -1000, -1000, 299, 13531, -1000, - -1000, -1000, 966, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 749, 195, -1000, 9845, 749, 749, 749, 749, 749, + 749, 749, 749, 10194, 749, 749, 749, 749, 749, 749, + 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, + -1000, -1000, 969, -1000, 806, -1000, -1000, -1000, 918, 10194, + 10194, 969, -1000, 884, 8785, -1000, -1000, 952, -1000, -1000, + -1000, -1000, 398, 1008, -1000, 11939, 191, 1006, 16147, -1000, + 14744, 15798, 751, 7026, -116, -1000, -1000, -1000, 320, 14046, + -1000, -1000, -1000, 901, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -2711,186 +2764,186 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 717, 17028, -1000, 2462, -1000, 614, 4333, - 152, 614, 333, 614, 17028, 17028, 4333, 4333, 4333, 71, - 92, 83, 17028, 810, 146, 17028, 1009, 892, 17028, 614, - 614, -1000, 5785, -1000, 4333, 348, -1000, 478, 9679, 4333, - 4333, 4333, 17028, 4333, 4333, -1000, 470, -1000, -1000, 338, - -1000, -1000, -1000, -1000, -1000, -1000, 4333, 4333, -1000, 1064, - 337, -1000, -1000, -1000, -1000, 9679, 261, -1000, 891, -1000, - -1000, 1, -1000, -1000, -1000, -1000, -1000, 1091, -1000, -1000, - -1000, -132, -1000, -1000, 9679, 9679, 9679, 9679, 587, 252, - 10726, 471, 381, 10726, 10726, 10726, 10726, 10726, 10726, 10726, - 10726, 10726, 10726, 10726, 10726, 10726, 10726, 10726, 736, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 614, -1000, 1088, - 718, 718, 227, 227, 227, 227, 227, 227, 227, 227, - 227, 11075, 7223, 5785, 631, 706, 1029, 8270, 8270, 9679, - 9679, 8968, 8619, 8270, 977, 328, 666, 17028, -1000, -1000, - 10377, -1000, -1000, -1000, -1000, -1000, 454, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 17028, 17028, 8270, 8270, 8270, 8270, - 8270, 1022, 631, 1057, -1000, 1082, 247, 660, 798, -1000, - 594, 1022, 13182, 611, -1000, 1057, -1000, -1000, -1000, 17028, - -1000, -1000, 14927, -1000, -1000, 5422, 17028, 95, 17028, -1000, - 699, 1090, -1000, -1000, -1000, 1011, 12484, 12833, 17028, 811, - 535, -1000, -1000, 201, 6148, -128, -1000, 6148, 729, -1000, - -123, -104, 7572, 211, -1000, -1000, -1000, -1000, 3970, 483, - 539, 360, -74, -1000, -1000, -1000, 842, -1000, 842, 842, - 842, 842, -37, -37, -37, -37, -1000, -1000, -1000, -1000, - -1000, 861, 858, -1000, 842, 842, 842, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 697, 17543, -1000, 330, -1000, 564, + 4848, 108, 564, 360, 564, 17543, 17543, 4848, 4848, 4848, + 47, 80, 77, 17543, 557, 750, 105, 17543, 946, 836, + 17543, 564, 564, -1000, 6300, -1000, 4848, 341, -1000, 552, + 10194, 4848, 4848, 4848, 17543, 4848, 4848, -1000, 550, -1000, + -1000, 336, -1000, -1000, -1000, -1000, -1000, -1000, 4848, 4848, + -1000, 1002, 331, -1000, -1000, -1000, -1000, 10194, 279, -1000, + 833, -1000, -1000, 26, -1000, -1000, -1000, -1000, -1000, 1028, + -1000, -1000, -1000, -122, -1000, -1000, 10194, 10194, 10194, 10194, + 429, 283, 11241, 420, 276, 11241, 11241, 11241, 11241, 11241, + 11241, 11241, 11241, 11241, 11241, 11241, 11241, 11241, 11241, 11241, + 551, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 564, + -1000, 997, 633, 633, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 11590, 7738, 6300, 665, 676, 969, 8785, + 8785, 10194, 10194, 9483, 9134, 8785, 906, 339, 387, 17543, + -1000, -1000, 10892, -1000, -1000, -1000, -1000, -1000, 577, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 17543, 17543, 8785, 8785, + 8785, 8785, 8785, 964, 665, 952, -1000, 1022, 239, 582, + 743, -1000, 364, 964, 13697, 746, -1000, 952, -1000, -1000, + -1000, 17543, -1000, -1000, 15442, -1000, -1000, 5937, 17543, 59, + 17543, -1000, 735, 788, -1000, -1000, -1000, 948, 12999, 13348, + 17543, 722, 667, -1000, -1000, 189, 6663, -116, -1000, 6663, + 729, -1000, -113, -124, 8087, 206, -1000, -1000, -1000, -1000, + 4485, 229, 621, 491, -71, -1000, -1000, -1000, 761, -1000, + 761, 761, 761, 761, -19, -19, -19, -19, -1000, -1000, + -1000, -1000, -1000, 786, 785, -1000, 761, 761, 761, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 856, 856, 856, 850, 850, - 877, -1000, 17028, 4333, 1006, 4333, -1000, 100, -1000, -1000, - -1000, 17028, 17028, 17028, 17028, 17028, 180, 17028, 17028, 792, - -1000, 17028, 4333, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 666, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17028, - -1000, -1000, -1000, -1000, 17028, 348, 17028, 17028, 666, -1000, - 17028, 17028, -1000, -1000, -1000, -1000, -1000, 666, 252, 488, - 274, -1000, -1000, 398, -1000, -1000, 1779, -1000, -1000, -1000, - -1000, 471, 10726, 10726, 10726, 449, 1779, 2274, 708, 592, - 227, 501, 501, 229, 229, 229, 229, 229, 349, 349, - -1000, -1000, -1000, 454, -1000, -1000, -1000, 454, 8270, 8270, - 783, 744, 200, -1000, 789, -1000, -1000, 1022, 695, 695, - 586, 548, 326, 1063, 695, 324, 1053, 695, 695, 8270, - -1000, -1000, 325, -1000, 9679, 454, -1000, 199, -1000, 857, - 748, 741, 695, 454, 454, 695, 695, 982, -1000, -1000, - 937, 9679, 9679, 9679, -1000, -1000, -1000, 982, 1034, -1000, - 956, 955, 1044, 8270, 14229, 1057, -1000, -1000, -1000, 198, - 1044, 938, 744, -1000, 17028, 14229, 14229, 14229, 14229, 14229, - -1000, 924, 905, -1000, 928, 904, 936, 17028, -1000, 704, - 631, 12484, 235, 744, -1000, 14578, -1000, -1000, 95, 661, - 14229, 17028, -1000, -1000, 14229, 17028, 5059, -1000, 729, -128, - -137, -1000, -1000, -1000, -1000, 666, -1000, 743, 720, 3607, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 855, 614, -1000, - 991, 246, 343, 614, 987, -1000, -1000, -1000, 970, -1000, - 344, -76, -1000, -1000, 417, -37, -37, -1000, -1000, 211, - 963, 211, 211, 211, 467, 467, -1000, -1000, -1000, -1000, - 415, -1000, -1000, -1000, 384, -1000, 887, 17028, 4333, -1000, - -1000, -1000, -1000, 254, 254, 264, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 88, 865, -1000, - -1000, -1000, -1000, 6, 64, 139, -1000, 4333, -1000, 337, - 337, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 449, 1779, 2259, -1000, 10726, 10726, -1000, -1000, 695, 695, - 8270, 5785, 1029, 982, -1000, -1000, 140, 736, 140, 10726, - 10726, -1000, 10726, 10726, -1000, -169, 721, 313, -1000, 9679, - 502, -1000, 5785, -1000, 10726, 10726, -1000, -1000, -1000, -1000, - -1000, -1000, 945, 666, 666, -1000, -1000, 17028, -1000, -1000, - -1000, -1000, 1037, 9679, -1000, 711, -1000, 4696, 1022, 886, - 17028, 744, 1091, 12484, 17028, 761, -1000, 284, 1090, 854, - 885, 826, -1000, -1000, -1000, -1000, 890, -1000, 866, -1000, - -1000, -1000, -1000, -1000, 631, -1000, 166, 164, 159, 17028, - -1000, 1044, 14229, 654, -1000, 654, -1000, 197, -1000, -1000, - -1000, -138, -111, -1000, -1000, -1000, 3970, -1000, 3970, 17028, - 105, -1000, 614, 614, -1000, -1000, -1000, 851, 884, 10726, - -1000, -1000, -1000, 527, 211, 211, -1000, 346, -1000, -1000, - -1000, 692, -1000, 689, 622, 682, 17028, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 781, 781, 781, + 763, 763, 803, -1000, 17543, 4848, 945, 4848, -1000, 97, + -1000, -1000, -1000, 17543, 17543, 17543, 17543, 17543, 160, -1000, + 17543, 17543, 740, -1000, 17543, 4848, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 387, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 17543, -1000, -1000, -1000, -1000, 17543, 341, 17543, + 17543, 387, -1000, 17543, 17543, -1000, -1000, -1000, -1000, -1000, + 387, 283, 302, 337, -1000, -1000, 432, -1000, -1000, 1686, + -1000, -1000, -1000, -1000, 420, 11241, 11241, 11241, 161, 1686, + 2028, 1593, 1561, 211, 296, 296, 219, 219, 219, 219, + 219, 540, 540, -1000, -1000, -1000, 577, -1000, -1000, -1000, + 577, 8785, 8785, 739, 749, 188, -1000, 784, -1000, -1000, + 964, 662, 662, 413, 340, 290, 993, 662, 273, 992, + 662, 662, 8785, -1000, -1000, 400, -1000, 10194, 577, -1000, + 187, -1000, 348, 738, 737, 662, 577, 577, 662, 662, + 918, -1000, -1000, 881, 10194, 10194, 10194, -1000, -1000, -1000, + 918, 961, -1000, 889, 888, 981, 8785, 14744, 952, -1000, + -1000, -1000, 185, 981, 731, 749, -1000, 17543, 14744, 14744, + 14744, 14744, 14744, -1000, 857, 854, -1000, 853, 847, 872, + 17543, -1000, 670, 665, 12999, 199, 749, -1000, 15093, -1000, + -1000, 59, 725, 14744, 17543, -1000, -1000, 14744, 17543, 5574, + -1000, 729, -116, -67, -1000, -1000, -1000, -1000, 387, -1000, + 570, 724, 4122, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 769, 564, -1000, 938, 222, 295, 564, 936, -1000, -1000, + -1000, 907, -1000, 389, -80, -1000, -1000, 530, -19, -19, + -1000, -1000, 206, 899, 206, 206, 206, 544, 544, -1000, + -1000, -1000, -1000, 528, -1000, -1000, -1000, 508, -1000, 831, + 17543, 4848, -1000, -1000, -1000, -1000, 1544, 1544, 258, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 17028, -1000, -1000, -1000, - -1000, -1000, 17028, -175, 614, 17028, 17028, 17028, 17028, -1000, - 348, 348, -1000, 10726, 1779, 1779, -1000, -1000, 454, -1000, - 1022, -1000, 454, 842, 842, -1000, 842, 850, -1000, 842, - -14, 842, -21, 454, 454, 2188, 2163, 1701, 546, 744, - -164, -1000, 666, 9679, -1000, 1912, 1735, -1000, -1000, 1032, - 1024, 666, -1000, -1000, -1000, 996, 808, 570, -1000, -1000, - 7921, 676, 192, 673, -1000, 1029, 17028, 9679, -1000, -1000, - 9679, 845, -1000, 9679, -1000, -1000, -1000, 1029, 744, 744, - 744, 673, 1029, 654, -1000, -1000, 239, -1000, -1000, -1000, - 3607, -1000, 664, -1000, 842, -1000, -1000, -1000, 17028, -64, - 1081, 1779, -1000, -1000, -1000, -1000, -1000, -37, 448, -37, - 378, -1000, 377, 4333, -1000, -1000, -1000, -1000, 1001, -1000, - 5785, -1000, -1000, 841, 870, -1000, -1000, -1000, -1000, 1779, - -1000, 982, -1000, -1000, 149, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, 10726, 10726, 10726, 10726, 10726, 1022, 446, - 666, 10726, 10726, -1000, 9679, 9679, 986, -1000, 744, -1000, - 860, 17028, 17028, -1000, 17028, 1022, -1000, 666, 666, 17028, - 666, 13880, 17028, 17028, 12122, 1022, -1000, 204, 17028, -1000, - 648, -1000, 251, -1000, -61, 211, -1000, 211, 525, 504, - -1000, 744, 600, -1000, 276, 17028, 17028, -1000, -1000, -1000, - 857, 857, 857, 857, 82, 454, -1000, 857, 857, 666, - 582, 1079, -1000, 744, 1091, 170, -1000, -1000, -1000, 626, - 624, -1000, 624, 624, 235, -1000, 204, -1000, 614, 270, - 429, -1000, 94, 17028, 350, 976, -1000, 975, -1000, -1000, - -1000, -1000, -1000, 87, 5785, 3970, 574, -1000, -1000, -1000, - -1000, -1000, 454, 54, -184, -1000, -1000, -1000, 17028, 570, - 17028, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 362, -1000, - -1000, 17028, -1000, -1000, 420, -1000, -1000, 554, -1000, 17028, - -1000, -1000, 865, -1000, 944, -173, -187, 503, -1000, -1000, - 831, -1000, -1000, 87, 954, -175, -1000, 930, -1000, 17028, - -1000, 76, -1000, -182, 537, 78, -185, 883, 744, -188, - 879, -1000, 1051, 10028, -1000, -1000, 1077, 234, 234, 857, - 454, -1000, -1000, -1000, 98, 410, -1000, -1000, -1000, -1000, - -1000, -1000, + 57, 792, -1000, -1000, -1000, -1000, -11, 46, 99, -1000, + 4848, -1000, 331, 331, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 161, 1686, 1339, -1000, 11241, 11241, -1000, + -1000, 662, 662, 8785, 6300, 969, 918, -1000, -1000, 118, + 551, 118, 11241, 11241, -1000, 11241, 11241, -1000, -165, 744, + 359, -1000, 10194, 503, -1000, 6300, -1000, 11241, 11241, -1000, + -1000, -1000, -1000, -1000, -1000, 877, 387, 387, -1000, -1000, + 17543, -1000, -1000, -1000, -1000, 975, 10194, -1000, 713, -1000, + 5211, 964, 830, 17543, 749, 1028, 12999, 17543, 719, -1000, + 308, 788, 768, 829, 694, -1000, -1000, -1000, -1000, 850, + -1000, 780, -1000, -1000, -1000, -1000, -1000, 665, -1000, 123, + 122, 114, 17543, -1000, 981, 14744, 680, -1000, 680, -1000, + 183, -1000, -1000, -1000, -135, -137, -1000, -1000, -1000, 4485, + -1000, 4485, 17543, 78, -1000, 564, 564, -1000, -1000, -1000, + 764, 826, 11241, -1000, -1000, -1000, 599, 206, 206, -1000, + 353, -1000, -1000, -1000, 660, -1000, 655, 706, 651, 17543, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 17543, + -1000, -1000, -1000, -1000, -1000, 17543, -171, 564, 17543, 17543, + 17543, 17543, -1000, 341, 341, -1000, 11241, 1686, 1686, -1000, + -1000, 577, -1000, 964, -1000, 577, 761, 761, -1000, 761, + 763, -1000, 761, 6, 761, -1, 577, 577, 1866, 1851, + 1746, 453, 749, -159, -1000, 387, 10194, -1000, 852, 770, + -1000, -1000, 971, 962, 387, -1000, -1000, -1000, 908, 708, + 631, -1000, -1000, 8436, 649, 182, 636, -1000, 969, 17543, + 10194, -1000, -1000, 10194, 762, -1000, 10194, -1000, -1000, -1000, + 969, 749, 749, 749, 636, 969, 680, -1000, -1000, 226, + -1000, -1000, -1000, 4122, -1000, 626, -1000, 761, -1000, -1000, + -1000, 17543, -63, 1016, 1686, -1000, -1000, -1000, -1000, -1000, + -19, 535, -19, 502, -1000, 436, 4848, -1000, -1000, -1000, + -1000, 941, -1000, 6300, -1000, -1000, 758, 796, -1000, -1000, + -1000, -1000, 1686, -1000, 918, -1000, -1000, 137, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 11241, 11241, 11241, 11241, + 11241, 964, 533, 387, 11241, 11241, -1000, 10194, 10194, 935, + -1000, 749, -1000, 748, 17543, 17543, -1000, 17543, 964, -1000, + 387, 387, 17543, 387, 14395, 17543, 17543, 12637, 964, -1000, + 180, 17543, -1000, 624, -1000, 203, -1000, -111, 206, -1000, + 206, 595, 579, -1000, 749, 689, -1000, 305, 17543, 17543, + -1000, -1000, -1000, 348, 348, 348, 348, 71, 577, -1000, + 348, 348, 387, 644, 1014, -1000, 749, 1028, 176, -1000, + -1000, -1000, 617, 615, -1000, 615, 615, 199, -1000, 180, + -1000, 564, 297, 525, -1000, 74, 17543, 392, 916, -1000, + 912, -1000, -1000, -1000, -1000, -1000, 56, 6300, 4485, 613, + -1000, -1000, -1000, -1000, -1000, 577, 58, -175, -1000, -1000, + -1000, 17543, 631, 17543, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 408, -1000, -1000, 17543, -1000, -1000, 446, -1000, -1000, + 608, -1000, 17543, -1000, -1000, 792, -1000, 870, -169, -180, + 583, -1000, -1000, 757, -1000, -1000, 56, 887, -171, -1000, + 863, -1000, 17543, -1000, 53, -1000, -173, 593, 51, -177, + 812, 749, -181, 807, -1000, 991, 10543, -1000, -1000, 1013, + 200, 200, 348, 577, -1000, -1000, -1000, 83, 445, -1000, + -1000, -1000, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 1360, 1359, 27, 67, 58, 1358, 1357, 1356, 1355, - 93, 92, 91, 1354, 1353, 1352, 1351, 1348, 1347, 1344, - 1342, 1339, 1335, 1332, 1329, 1327, 1324, 1323, 1322, 1321, - 1320, 1319, 1318, 122, 1310, 1304, 1302, 1301, 76, 1300, - 1298, 1296, 1295, 1293, 38, 222, 44, 66, 1289, 57, - 1266, 1287, 47, 63, 60, 1286, 25, 1285, 1282, 72, - 1281, 1279, 56, 1278, 1274, 2033, 1273, 54, 1272, 10, - 26, 1270, 1261, 1259, 1257, 79, 170, 1256, 1252, 9, - 1248, 1246, 143, 1245, 65, 15, 7, 19, 17, 1243, - 69, 1241, 14, 1240, 62, 1239, 1236, 1235, 1234, 32, - 1229, 59, 1228, 118, 23, 1227, 31, 42, 35, 20, - 5, 1226, 1224, 18, 70, 48, 73, 1223, 1222, 1220, - 561, 1218, 50, 1217, 1216, 1212, 29, 77, 89, 427, - 1211, 1208, 1207, 1203, 1202, 37, 937, 1299, 115, 87, - 1201, 1200, 1197, 2153, 40, 55, 12, 1196, 1192, 1190, - 30, 328, 36, 462, 1189, 34, 1187, 1186, 1184, 1183, - 1178, 1176, 1175, 308, 1173, 1171, 1170, 90, 71, 64, - 21, 1169, 1168, 1164, 1163, 49, 75, 1160, 1159, 52, - 1157, 1156, 22, 1150, 1149, 1148, 1147, 1144, 24, 6, - 1131, 13, 1130, 16, 1129, 33, 1127, 3, 1126, 11, - 1122, 2, 0, 1121, 4, 41, 1, 1111, 8, 1106, - 1103, 1097, 110, 709, 68, 1095, 78, + 0, 1288, 1286, 32, 71, 67, 1283, 1282, 1279, 1278, + 99, 97, 94, 1277, 1276, 1274, 1273, 1272, 1270, 1269, + 1268, 1264, 1262, 1260, 1255, 1254, 1251, 1249, 1248, 1247, + 1246, 1245, 1244, 88, 1242, 1241, 1240, 1239, 77, 1237, + 1234, 1232, 1230, 1229, 50, 243, 56, 66, 1226, 70, + 749, 1225, 30, 64, 61, 1224, 44, 1223, 1222, 81, + 1221, 1220, 58, 1219, 1215, 52, 1205, 57, 1204, 7, + 26, 1202, 1200, 1199, 1198, 92, 1882, 1197, 1190, 15, + 1189, 1179, 89, 1178, 72, 20, 11, 12, 22, 1176, + 69, 1175, 8, 1172, 65, 1171, 1170, 1169, 1168, 18, + 1167, 63, 1164, 29, 36, 1158, 14, 59, 34, 25, + 10, 1154, 1153, 16, 82, 68, 73, 1152, 1151, 1150, + 532, 1149, 1148, 62, 1147, 1146, 1142, 40, 87, 98, + 534, 1139, 1137, 1136, 1135, 1132, 35, 1054, 1718, 37, + 78, 1130, 1129, 1128, 2665, 42, 60, 17, 1127, 1126, + 1125, 38, 85, 48, 489, 1123, 41, 1122, 1121, 1120, + 1119, 1118, 1117, 1116, 189, 1113, 1112, 1099, 24, 23, + 76, 27, 1098, 1094, 1092, 1086, 54, 75, 1085, 1084, + 49, 1083, 1082, 28, 1081, 1080, 1079, 1077, 1070, 31, + 6, 1065, 19, 1061, 13, 1060, 21, 1058, 4, 1056, + 9, 1055, 3, 0, 1052, 5, 55, 2, 1049, 1, + 1048, 1046, 1042, 1622, 204, 74, 1041, 108, } var yyR1 = [...]int{ - 0, 210, 211, 211, 1, 1, 1, 1, 1, 1, + 0, 211, 212, 212, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 202, 202, 202, 21, 3, 3, 3, 3, 2, 2, + 203, 203, 203, 21, 3, 3, 3, 3, 2, 2, 8, 9, 4, 5, 5, 10, 10, 37, 37, 11, - 12, 12, 12, 12, 214, 214, 59, 59, 60, 60, + 12, 12, 12, 12, 215, 215, 59, 59, 60, 60, 107, 107, 13, 14, 14, 116, 116, 115, 115, 115, - 117, 117, 117, 117, 153, 153, 15, 15, 15, 15, - 15, 15, 15, 204, 204, 203, 201, 201, 200, 200, - 199, 22, 184, 186, 186, 185, 185, 185, 185, 176, - 156, 156, 156, 156, 159, 159, 157, 157, 157, 157, - 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, - 160, 160, 160, 160, 160, 161, 161, 161, 161, 161, - 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, - 162, 162, 162, 162, 162, 162, 162, 162, 175, 175, - 163, 163, 169, 169, 170, 170, 170, 172, 172, 173, - 173, 130, 130, 130, 165, 165, 166, 166, 171, 171, - 167, 167, 167, 168, 168, 168, 174, 174, 174, 174, - 174, 164, 164, 177, 177, 194, 194, 193, 193, 193, - 183, 183, 190, 190, 190, 190, 190, 180, 180, 180, - 181, 181, 179, 179, 182, 182, 192, 192, 191, 178, - 178, 195, 195, 195, 195, 207, 208, 206, 206, 206, - 206, 206, 187, 187, 187, 188, 188, 188, 189, 189, - 189, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 205, 205, - 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, - 205, 205, 198, 196, 196, 197, 197, 17, 23, 23, + 117, 117, 117, 117, 154, 154, 15, 15, 15, 15, + 15, 15, 15, 205, 205, 204, 202, 202, 201, 201, + 200, 22, 185, 187, 187, 186, 186, 186, 186, 177, + 157, 157, 157, 157, 160, 160, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 159, 159, 159, 159, 159, + 161, 161, 161, 161, 161, 162, 162, 162, 162, 162, + 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, + 163, 163, 163, 163, 163, 163, 163, 163, 176, 176, + 164, 164, 170, 170, 171, 171, 171, 173, 173, 174, + 174, 131, 131, 131, 166, 166, 167, 167, 172, 172, + 168, 168, 168, 169, 169, 169, 175, 175, 175, 175, + 175, 165, 165, 178, 178, 195, 195, 194, 194, 194, + 184, 184, 191, 191, 191, 191, 191, 181, 181, 181, + 182, 182, 180, 180, 183, 183, 193, 193, 192, 179, + 179, 196, 196, 196, 196, 208, 209, 207, 207, 207, + 207, 207, 188, 188, 188, 189, 189, 189, 190, 190, + 190, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 206, 206, + 206, 206, 206, 206, 206, 206, 206, 206, 206, 206, + 206, 206, 199, 197, 197, 198, 198, 17, 23, 23, 18, 18, 18, 18, 18, 19, 19, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 123, 123, - 209, 209, 125, 125, 121, 121, 124, 124, 122, 122, - 122, 126, 126, 126, 127, 127, 154, 154, 154, 26, - 26, 28, 28, 29, 30, 30, 148, 148, 149, 149, + 25, 25, 25, 25, 25, 25, 25, 25, 124, 124, + 210, 210, 126, 126, 122, 122, 125, 125, 123, 123, + 123, 127, 127, 127, 128, 128, 155, 155, 155, 26, + 26, 28, 28, 29, 30, 30, 149, 149, 150, 150, 31, 32, 36, 36, 36, 36, 36, 36, 39, 39, 39, 7, 7, 7, 7, 35, 35, 35, 6, 6, - 27, 27, 27, 27, 20, 215, 33, 34, 34, 38, + 27, 27, 27, 27, 20, 216, 33, 34, 34, 38, 38, 38, 40, 40, 40, 43, 43, 43, 46, 46, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, - 49, 45, 45, 47, 47, 47, 47, 140, 140, 140, - 139, 139, 51, 51, 52, 52, 53, 53, 54, 54, + 49, 45, 45, 47, 47, 47, 47, 141, 141, 141, + 140, 140, 51, 51, 52, 52, 53, 53, 54, 54, 54, 91, 68, 68, 106, 106, 108, 108, 55, 55, - 55, 55, 56, 56, 57, 57, 58, 58, 147, 147, - 146, 146, 146, 145, 145, 61, 61, 61, 63, 62, + 55, 55, 56, 56, 57, 57, 58, 58, 148, 148, + 147, 147, 147, 146, 146, 61, 61, 61, 63, 62, 62, 62, 62, 64, 64, 66, 66, 65, 65, 67, 69, 69, 69, 69, 69, 70, 70, 50, 50, 50, 50, 50, 50, 50, 50, 119, 119, 72, 72, 71, @@ -2903,36 +2956,21 @@ var yyR1 = [...]int{ 76, 76, 76, 76, 80, 80, 80, 80, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 79, 79, 216, 216, 82, + 79, 79, 79, 79, 79, 79, 79, 217, 217, 82, 81, 81, 81, 81, 81, 81, 81, 42, 42, 42, - 42, 42, 152, 152, 155, 155, 155, 155, 155, 155, - 155, 155, 155, 155, 155, 155, 155, 95, 95, 41, + 42, 42, 153, 153, 156, 156, 156, 156, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 95, 95, 41, 41, 93, 93, 94, 96, 96, 92, 92, 92, 75, 75, 75, 75, 75, 75, 75, 75, 77, 77, 77, 97, 97, 98, 98, 99, 99, 100, 100, 101, 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 74, 74, 74, 74, 105, 105, 105, 105, 109, 109, 86, 86, 88, 88, 87, 89, 110, 110, 113, 111, 111, - 114, 114, 114, 114, 114, 112, 112, 112, 142, 142, - 142, 118, 118, 128, 128, 129, 129, 120, 120, 131, - 131, 131, 131, 131, 131, 131, 131, 131, 131, 132, - 132, 132, 133, 133, 134, 134, 134, 141, 141, 137, - 137, 138, 138, 143, 143, 144, 144, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 135, 135, 135, 135, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, + 114, 114, 114, 114, 114, 112, 112, 112, 143, 143, + 143, 118, 118, 129, 129, 130, 130, 120, 120, 132, + 132, 132, 132, 132, 132, 132, 132, 132, 132, 121, + 121, 121, 133, 133, 133, 134, 134, 135, 135, 135, + 142, 142, 138, 138, 139, 139, 144, 144, 145, 145, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, @@ -2944,11 +2982,26 @@ var yyR1 = [...]int{ 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, - 136, 136, 136, 136, 136, 212, 213, 150, 151, 151, - 151, + 136, 136, 136, 136, 136, 136, 136, 136, 136, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 213, 214, + 151, 152, 152, 152, } var yyR2 = [...]int{ @@ -3021,7 +3074,8 @@ var yyR2 = [...]int{ 3, 3, 3, 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, 0, 2, 0, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 1, 1, 1, 1, 0, 1, 1, 0, 2, 1, + 2, 3, 0, 1, 1, 1, 1, 0, 1, 1, + 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -3052,21 +3106,20 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, - 1, + 0, 0, 1, 1, } var yyChk = [...]int{ - -1000, -210, -1, -3, -8, -9, -10, -11, -12, -13, + -1000, -211, -1, -3, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -24, -25, -26, -28, - -29, -30, -31, -32, -6, -27, -20, -21, -4, -212, + -29, -30, -31, -32, -6, -27, -20, -21, -4, -213, 6, 7, 8, -37, 10, 11, 31, -22, 124, 125, 127, 126, 160, 128, 153, 54, 174, 175, 177, 178, 179, 180, -39, 158, 159, 32, 33, 130, 35, 58, - 9, 267, 155, 154, 26, -211, 369, -38, 5, -99, - 16, -3, -33, -215, -33, -33, -33, -33, -33, -33, - -184, -186, 58, 97, -134, 134, 78, 259, 131, 132, - 138, -137, -202, -136, 61, 62, 63, 277, 146, 309, + 9, 267, 155, 154, 26, -212, 369, -38, 5, -99, + 16, -3, -33, -216, -33, -33, -33, -33, -33, -33, + -185, -187, 58, 97, -135, 134, 78, 259, 131, 132, + 138, -138, -203, -137, 61, 62, 63, 277, 146, 309, 310, 174, 188, 182, 209, 201, 278, 311, 147, 199, 202, 246, 144, 312, 229, 236, 72, 177, 255, 313, 156, 197, 193, 314, 286, 191, 28, 315, 238, 214, @@ -3084,180 +3137,180 @@ var yyChk = [...]int{ 205, 165, 360, 361, 195, 196, 210, 183, 206, 176, 366, 167, 160, 362, 256, 227, 283, 203, 200, 171, 363, 168, 169, 364, 367, 242, 232, 243, 244, 233, - 172, 280, 252, 198, 228, -120, 134, 259, 131, 233, - 136, 132, 132, 133, 134, 259, 131, 132, -65, -143, - -202, -136, 134, 132, 115, 202, 246, 124, 230, 241, - 242, 238, -125, 239, 166, -154, 132, -121, 229, 232, - 233, 172, -209, -202, 240, 248, 247, 234, 244, 243, - -143, 176, -148, 181, -137, 179, -65, -36, 365, 128, - -150, -150, 231, 231, -150, -85, -50, -71, 81, -76, + 172, 280, 252, 198, 228, -121, 134, 259, 131, 233, + 280, 132, 132, 133, 134, 259, 131, 132, -65, -144, + -203, -137, 134, 132, 115, 202, 246, 124, 230, 241, + 242, 238, -126, 239, 166, -155, 132, -122, 229, 232, + 233, 172, -210, -203, 240, 248, 247, 234, 244, 243, + -144, 176, -149, 181, -138, 179, -65, -36, 365, 128, + -151, -151, 231, 231, -151, -85, -50, -71, 81, -76, 30, 24, -75, -72, -92, -89, -90, 115, 116, 118, 117, 119, 104, 105, 112, 82, 120, -80, -78, -79, -81, 65, 64, 73, 66, 67, 68, 69, 74, 75, - 76, -137, -143, -87, -212, 48, 49, 268, 269, 270, + 76, -138, -144, -87, -213, 48, 49, 268, 269, 270, 271, 276, 272, 84, 37, 258, 266, 265, 264, 262, 263, 260, 261, 274, 275, 137, 259, 131, 110, 267, - -202, -136, -5, -4, -212, 6, 21, 22, -103, 18, - 17, -213, 60, -40, -48, 43, 44, -49, 22, 36, - 47, 45, -34, -47, 106, -50, -143, -47, -120, -120, - -120, -111, -153, 176, -114, 248, 247, -138, -112, -137, - -135, 246, 202, 245, 129, 284, 80, 23, 25, 224, - 83, 115, 17, 84, 114, 268, 124, 52, 285, 260, - 261, 258, 270, 271, 259, 230, 30, 11, 287, 26, - 154, 22, 36, 108, 126, 87, 88, 157, 24, 155, - 76, 290, 20, 55, 12, 14, 291, 292, 15, 137, - 136, 99, 133, 50, 9, 120, 27, 96, 46, 293, - 29, 294, 295, 296, 297, 48, 97, 18, 262, 263, - 32, 298, 276, 161, 110, 53, 39, 81, 299, 300, - 74, 301, 77, 56, 78, 16, 51, 302, 303, 304, - 305, 98, 127, 267, 49, 306, 131, 6, 273, 31, - 153, 47, 307, 132, 86, 274, 275, 135, 75, 5, - 138, 33, 10, 54, 57, 264, 265, 266, 37, 85, - 13, 308, 79, -185, 97, -176, -202, -65, 133, -65, - 267, -129, 137, -129, -129, 132, -65, -202, -202, 124, - 126, 129, 56, -23, -65, -128, 137, -202, -128, -128, - -128, -65, 121, -65, -202, 31, -126, 97, 13, 259, - -202, 166, 132, 167, 134, -127, 97, -127, -127, -180, - 133, 34, 145, -151, -212, -138, 170, 171, -151, -124, - -123, 236, 237, 231, 235, 13, 171, 231, 169, -126, - -151, 135, -137, -35, -137, 65, -7, -3, -11, -10, - -12, 89, -150, -150, 59, 80, 78, 79, 96, -50, - -73, 99, 81, 97, 98, 83, 101, 100, 111, 104, - 105, 106, 107, 108, 109, 110, 102, 103, 114, 89, - 90, 91, 92, 93, 94, 95, -119, -212, -90, -212, - 122, 123, -76, -76, -76, -76, -76, -76, -76, -76, - -76, -76, -212, 121, -2, -85, -4, -212, -212, -212, - -212, -212, -212, -212, -212, -95, -50, -212, -216, -82, - -212, -216, -82, -216, -82, -216, -212, -216, -82, -216, - -82, -216, -216, -82, -212, -212, -212, -212, -212, -212, - -212, -99, -3, -33, -104, 20, 32, -50, -100, -101, - -50, -99, 39, -45, -47, -49, 43, 44, 71, 12, - -140, -139, 23, -137, 65, 121, 12, -66, 27, -65, - -52, -53, -54, -55, -68, -91, -212, -65, 12, -59, - -60, -65, -67, -143, 59, 176, -114, -153, -116, -115, - 249, 251, 89, -142, -137, 65, 30, 31, 60, 59, - -65, -156, -159, -161, -160, -162, -157, -158, 199, 200, - 115, 203, 205, 206, 207, 208, 209, 210, 211, 212, - 213, 214, 31, 156, 195, 196, 197, 198, 215, 216, - 217, 218, 219, 220, 221, 222, 182, 201, 278, 183, - 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, - -202, -151, 134, -202, 81, -202, -65, -65, -151, -151, - -151, 168, 168, 132, 132, 173, -65, 59, 135, -59, - 24, 56, -65, -202, -202, -144, -143, -135, -151, -126, - 65, -50, -151, -151, -151, -65, -151, -151, 65, -181, - 12, 99, -151, -151, 12, -122, 12, 99, -50, -127, - 56, -149, 179, 213, 366, 367, 368, -50, -50, -50, - -50, -83, 74, 81, 75, 76, -76, -84, -87, -90, - 70, 99, 97, 98, 83, -76, -76, -76, -76, -76, + -203, -137, -5, -4, -213, 6, 21, 22, -103, 18, + 17, -214, 60, -40, -48, 43, 44, -49, 22, 36, + 47, 45, -34, -47, 106, -50, -144, -47, -120, 136, + -120, -120, -111, -154, 176, -114, 248, 247, -139, -112, + -138, -136, 246, 202, 245, 129, 284, 80, 23, 25, + 224, 83, 115, 17, 84, 114, 268, 124, 52, 285, + 260, 261, 258, 270, 271, 259, 230, 30, 11, 287, + 26, 154, 22, 36, 108, 126, 87, 88, 157, 24, + 155, 76, 290, 20, 55, 12, 14, 291, 292, 15, + 137, 136, 99, 133, 50, 9, 120, 27, 96, 46, + 293, 29, 294, 295, 296, 297, 48, 97, 18, 262, + 263, 32, 298, 276, 161, 110, 53, 39, 81, 299, + 300, 74, 301, 77, 56, 78, 16, 51, 302, 303, + 304, 305, 98, 127, 267, 49, 306, 131, 6, 273, + 31, 153, 47, 307, 132, 86, 274, 275, 135, 75, + 5, 138, 33, 10, 54, 57, 264, 265, 266, 37, + 85, 13, 308, 79, -186, 97, -177, -203, -65, 133, + -65, 267, -130, 137, -130, -130, 132, -65, -203, -203, + 124, 126, 129, 56, 65, -23, -65, -129, 137, -203, + -129, -129, -129, -65, 121, -65, -203, 31, -127, 97, + 13, 259, -203, 166, 132, 167, 134, -128, 97, -128, + -128, -181, 133, 34, 145, -152, -213, -139, 170, 171, + -152, -125, -124, 236, 237, 231, 235, 13, 171, 231, + 169, -127, -152, 135, -138, -35, -138, 65, -7, -3, + -11, -10, -12, 89, -151, -151, 59, 80, 78, 79, + 96, -50, -73, 99, 81, 97, 98, 83, 101, 100, + 111, 104, 105, 106, 107, 108, 109, 110, 102, 103, + 114, 89, 90, 91, 92, 93, 94, 95, -119, -213, + -90, -213, 122, 123, -76, -76, -76, -76, -76, -76, + -76, -76, -76, -76, -213, 121, -2, -85, -4, -213, + -213, -213, -213, -213, -213, -213, -213, -95, -50, -213, + -217, -82, -213, -217, -82, -217, -82, -217, -213, -217, + -82, -217, -82, -217, -217, -82, -213, -213, -213, -213, + -213, -213, -213, -99, -3, -33, -104, 20, 32, -50, + -100, -101, -50, -99, 39, -45, -47, -49, 43, 44, + 71, 12, -141, -140, 23, -138, 65, 121, 12, -66, + 27, -65, -52, -53, -54, -55, -68, -91, -213, -65, + 12, -59, -60, -65, -67, -144, 59, 176, -114, -154, + -116, -115, 249, 251, 89, -143, -138, 65, 30, 31, + 60, 59, -65, -157, -160, -162, -161, -163, -158, -159, + 199, 200, 115, 203, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 31, 156, 195, 196, 197, 198, + 215, 216, 217, 218, 219, 220, 221, 222, 182, 201, + 278, 183, 184, 185, 186, 187, 188, 190, 191, 192, + 193, 194, -203, -152, 134, -203, 81, -203, -65, -65, + -152, -152, -152, 168, 168, 132, 132, 173, -65, 65, + 59, 135, -59, 24, 56, -65, -203, -203, -145, -144, + -136, -152, -127, 65, -50, -152, -152, -152, -65, -152, + -152, 65, -182, 12, 99, -152, -152, 12, -123, 12, + 99, -50, -128, 56, -150, 179, 213, 366, 367, 368, + -50, -50, -50, -50, -83, 74, 81, 75, 76, -76, + -84, -87, -90, 70, 99, 97, 98, 83, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, -76, - -152, -202, 65, -202, -75, -75, -137, -46, 22, 36, - -45, -138, -144, -135, -38, -213, -213, -99, -45, -45, - -50, -50, -92, 65, -45, -92, 65, -45, -45, -43, - 22, 36, -93, -94, 85, -92, -137, -143, -213, -76, - -137, -137, -45, -46, -46, -45, -45, -103, -213, 10, - 99, 59, 19, 59, -102, 25, 26, -103, -77, -137, - 66, 69, -51, 59, 12, -49, -65, -139, 106, -144, - -65, -107, 162, -65, 31, 59, -61, -63, -62, -64, - 46, 50, 52, 47, 48, 49, 53, -147, 23, -52, - -3, -212, -146, 162, -145, 23, -143, 65, -65, -59, - -214, 59, 12, 57, -214, 59, 121, -114, -116, 59, - 250, 252, 253, 56, 77, -50, -168, 114, -187, -188, - -189, -138, 65, 66, -176, -177, -178, -190, 148, -195, - 139, 141, 138, -179, 149, 133, 29, 60, -130, 74, - 81, -172, 227, -163, 58, -163, -163, -163, -163, -167, - 202, -167, -167, -167, 58, 58, -163, -163, -163, -169, - 58, -169, -169, -170, 58, -170, -141, 57, -65, -151, - 24, -151, -131, 129, 126, 127, -198, 125, 224, 202, - 72, 30, 16, 268, 162, 283, -202, 163, -65, -65, - -65, -65, -65, 129, 126, -65, -65, -65, -151, -65, - -65, -126, -143, -143, -65, -137, 74, 75, 76, -84, - -76, -76, -76, -44, 157, 80, -213, -213, -45, -45, - -212, 121, -5, -103, -213, -213, 59, 57, 23, 12, - 12, -213, 12, 12, -213, -213, -45, -96, -94, 87, - -50, -213, 121, -213, 59, 59, -213, -213, -213, -213, - -213, -104, 41, -50, -50, -101, -104, -118, 20, 12, - 37, 37, -70, 13, -47, -52, -49, 121, -70, -74, - 31, 37, -3, -212, -212, -110, -113, -92, -53, -54, - -54, -53, -54, 46, 46, 46, 51, 46, 51, 46, - -62, -143, -213, -213, -3, -69, 54, 136, 55, -212, - -145, -107, 57, -52, -65, -52, -67, -143, 106, -115, - -117, 254, 251, 257, -202, 65, 59, -189, 89, 58, - -202, 29, -179, -179, -182, -202, -182, 29, -165, 30, - 74, -173, 228, 66, -167, -167, -168, 31, -168, -168, - -168, -175, 65, -175, 66, 66, 56, -137, -151, -150, - -205, 144, 140, 148, 149, 142, 61, 62, 63, 133, - 29, 139, 141, 162, 138, -205, -132, -133, 135, 23, - 133, 29, 162, -204, 57, 168, 224, 168, 135, -151, - -122, -122, -44, 80, -76, -76, -213, -213, -46, -138, - -99, -104, -155, 115, 199, 156, 197, 193, 213, 204, - 226, 195, 227, -152, -155, -76, -76, -76, -76, 277, - -99, 88, -50, 86, -138, -76, -76, 42, -65, -97, - 14, -50, 106, -103, -109, 56, -110, -86, -88, -87, - -212, -105, -137, -108, -137, -70, 59, 89, -57, -56, - 56, 57, -58, 56, -56, 46, 46, -213, 133, 133, - 133, -108, -70, -52, -70, -70, 121, 251, 255, 256, - -188, -189, -192, -191, -137, -195, -182, -182, 58, -166, - 56, -76, 60, -168, -168, -202, 115, 60, 59, 60, - 59, 60, 59, -65, -150, -150, -65, -150, -137, -201, - 280, -203, -202, -137, -137, -137, -65, -126, -126, -76, - -213, -103, -213, -163, -163, -163, -170, -163, 187, -163, - 187, -213, -213, 20, 20, 20, 20, -212, -41, 273, - -50, 59, 59, -98, 15, 17, 28, -109, 59, -213, - -213, 59, 121, -213, 59, -99, -113, -50, -50, 58, - -50, -212, -212, -212, -213, -99, -70, 60, 59, -163, - -106, -137, -171, 224, 10, -167, 65, -167, 66, 66, - -151, 27, -200, -199, -138, 58, 57, -104, -167, -202, - -76, -76, -76, -76, -76, -103, 65, -76, -76, -50, - -85, 29, -88, 37, -3, -137, -137, -137, -103, -106, - -106, -213, -106, -106, -146, -103, -194, -193, 57, 143, - 72, -191, 60, 59, -174, 139, 29, 138, -79, -168, - -168, 60, 60, -212, 59, 89, -106, -65, -213, -213, - -213, -213, -42, 99, 280, -213, -213, -213, 10, -86, - 121, 60, -213, -213, -213, -69, -193, -202, -183, 89, - 65, 151, -137, -164, 72, 29, 29, -196, -197, 162, - -199, -189, 60, -213, 278, 53, 281, -110, -137, 66, - -65, 65, -213, 59, -137, -204, 42, 279, 282, 58, - -197, 37, -201, 42, -106, 164, 280, 60, 165, 281, - -207, -208, 56, -212, 282, -208, 56, 11, 10, -76, - 161, -206, 152, 147, 150, 31, -206, -213, -213, 146, - 30, 74, + -76, -76, -76, -153, -203, 65, -203, -75, -75, -138, + -46, 22, 36, -45, -139, -145, -136, -38, -214, -214, + -99, -45, -45, -50, -50, -92, 65, -45, -92, 65, + -45, -45, -43, 22, 36, -93, -94, 85, -92, -138, + -144, -214, -76, -138, -138, -45, -46, -46, -45, -45, + -103, -214, 10, 99, 59, 19, 59, -102, 25, 26, + -103, -77, -138, 66, 69, -51, 59, 12, -49, -65, + -140, 106, -145, -65, -107, 162, -65, 31, 59, -61, + -63, -62, -64, 46, 50, 52, 47, 48, 49, 53, + -148, 23, -52, -3, -213, -147, 162, -146, 23, -144, + 65, -65, -59, -215, 59, 12, 57, -215, 59, 121, + -114, -116, 59, 250, 252, 253, 56, 77, -50, -169, + 114, -188, -189, -190, -139, 65, 66, -177, -178, -179, + -191, 148, -196, 139, 141, 138, -180, 149, 133, 29, + 60, -131, 74, 81, -173, 227, -164, 58, -164, -164, + -164, -164, -168, 202, -168, -168, -168, 58, 58, -164, + -164, -164, -170, 58, -170, -170, -171, 58, -171, -142, + 57, -65, -152, 24, -152, -132, 129, 126, 127, -199, + 125, 224, 202, 72, 30, 16, 268, 162, 283, -203, + 163, -65, -65, -65, -65, -65, 129, 126, -65, -65, + -65, -152, -65, -65, -127, -144, -144, -65, -138, 74, + 75, 76, -84, -76, -76, -76, -44, 157, 80, -214, + -214, -45, -45, -213, 121, -5, -103, -214, -214, 59, + 57, 23, 12, 12, -214, 12, 12, -214, -214, -45, + -96, -94, 87, -50, -214, 121, -214, 59, 59, -214, + -214, -214, -214, -214, -104, 41, -50, -50, -101, -104, + -118, 20, 12, 37, 37, -70, 13, -47, -52, -49, + 121, -70, -74, 31, 37, -3, -213, -213, -110, -113, + -92, -53, -54, -54, -53, -54, 46, 46, 46, 51, + 46, 51, 46, -62, -144, -214, -214, -3, -69, 54, + 136, 55, -213, -146, -107, 57, -52, -65, -52, -67, + -144, 106, -115, -117, 254, 251, 257, -203, 65, 59, + -190, 89, 58, -203, 29, -180, -180, -183, -203, -183, + 29, -166, 30, 74, -174, 228, 66, -168, -168, -169, + 31, -169, -169, -169, -176, 65, -176, 66, 66, 56, + -138, -152, -151, -206, 144, 140, 148, 149, 142, 61, + 62, 63, 133, 29, 139, 141, 162, 138, -206, -133, + -134, 135, 23, 133, 29, 162, -205, 57, 168, 224, + 168, 135, -152, -123, -123, -44, 80, -76, -76, -214, + -214, -46, -139, -99, -104, -156, 115, 199, 156, 197, + 193, 213, 204, 226, 195, 227, -153, -156, -76, -76, + -76, -76, 277, -99, 88, -50, 86, -139, -76, -76, + 42, -65, -97, 14, -50, 106, -103, -109, 56, -110, + -86, -88, -87, -213, -105, -138, -108, -138, -70, 59, + 89, -57, -56, 56, 57, -58, 56, -56, 46, 46, + -214, 133, 133, 133, -108, -70, -52, -70, -70, 121, + 251, 255, 256, -189, -190, -193, -192, -138, -196, -183, + -183, 58, -167, 56, -76, 60, -169, -169, -203, 115, + 60, 59, 60, 59, 60, 59, -65, -151, -151, -65, + -151, -138, -202, 280, -204, -203, -138, -138, -138, -65, + -127, -127, -76, -214, -103, -214, -164, -164, -164, -171, + -164, 187, -164, 187, -214, -214, 20, 20, 20, 20, + -213, -41, 273, -50, 59, 59, -98, 15, 17, 28, + -109, 59, -214, -214, 59, 121, -214, 59, -99, -113, + -50, -50, 58, -50, -213, -213, -213, -214, -99, -70, + 60, 59, -164, -106, -138, -172, 224, 10, -168, 65, + -168, 66, 66, -152, 27, -201, -200, -139, 58, 57, + -104, -168, -203, -76, -76, -76, -76, -76, -103, 65, + -76, -76, -50, -85, 29, -88, 37, -3, -138, -138, + -138, -103, -106, -106, -214, -106, -106, -147, -103, -195, + -194, 57, 143, 72, -192, 60, 59, -175, 139, 29, + 138, -79, -169, -169, 60, 60, -213, 59, 89, -106, + -65, -214, -214, -214, -214, -42, 99, 280, -214, -214, + -214, 10, -86, 121, 60, -214, -214, -214, -69, -194, + -203, -184, 89, 65, 151, -138, -165, 72, 29, 29, + -197, -198, 162, -200, -190, 60, -214, 278, 53, 281, + -110, -138, 66, -65, 65, -214, 59, -138, -205, 42, + 279, 282, 58, -198, 37, -202, 42, -106, 164, 280, + 60, 165, 281, -208, -209, 56, -213, 282, -209, 56, + 11, 10, -76, 161, -207, 152, 147, 150, 31, -207, + -214, -214, 146, 30, 74, } var yyDef = [...]int{ 29, -2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 624, 0, - 365, 365, 365, 365, 365, 365, 365, 0, 694, 677, + 365, 365, 365, 365, 365, 365, 365, 0, 697, 689, 0, 0, 0, 0, -2, 330, 331, 0, 333, -2, - 0, 0, 342, 1007, 1007, 0, 0, 1007, 0, 1005, + 0, 0, 342, 1010, 1010, 0, 0, 1010, 0, 1008, 47, 48, 348, 349, 350, 1, 3, 0, 369, 632, 0, 0, -2, 367, 0, 0, 677, 677, 677, 0, - 76, 77, 0, 0, 0, 990, 0, 675, 675, 675, - 695, 696, 699, 700, 30, 31, 32, 826, 827, 828, - 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, - 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, - 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, - 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, - 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, - 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, - 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, - 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, - 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, - 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, - 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, - 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, - 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, - 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, - 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, - 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, - 989, 991, 992, 993, 994, 995, 996, 997, 998, 999, - 1000, 1001, 1002, 1003, 1004, 0, 0, 0, 0, 0, - 678, 0, 673, 0, 673, 673, 673, 0, 276, 447, - 703, 704, 990, 0, 0, 0, 321, 0, 324, 324, - 324, 290, 0, 292, 1008, 0, 1008, 0, 299, 0, - 0, 305, 321, 1008, 313, 327, 328, 315, 310, 311, - 329, 332, 0, 337, 340, 0, 355, 0, 867, 347, - 360, 361, 1007, 1007, 364, 33, 498, 457, 0, 463, + 76, 77, 0, 0, 0, 993, 0, 675, 675, 675, + 698, 699, 702, 703, 30, 31, 32, 829, 830, 831, + 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, + 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, + 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, + 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, + 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, + 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, + 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, + 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, + 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, + 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, + 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, + 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, + 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, + 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, + 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, + 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, + 992, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, + 1003, 1004, 1005, 1006, 1007, 0, 0, 0, 0, 0, + 0, 0, 673, 0, 673, 673, 673, 0, 276, 447, + 706, 707, 993, 0, 0, 0, 321, 0, 324, 324, + 324, 290, 0, 292, 1011, 0, 1011, 0, 299, 0, + 0, 305, 321, 1011, 313, 327, 328, 315, 310, 311, + 329, 332, 0, 337, 340, 0, 355, 0, 870, 347, + 360, 361, 1010, 1010, 364, 33, 498, 457, 0, 463, 465, 0, 500, 501, 502, 503, 504, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 530, 531, 532, 533, 609, 610, 611, 612, 613, 614, 615, 616, 467, @@ -3265,129 +3318,129 @@ var yyDef = [...]int{ 0, 0, 0, 597, 0, 567, 567, 567, 567, 567, 567, 567, 567, 0, 0, 0, 0, 0, 0, 0, -2, -2, 624, 43, 0, 365, 370, 371, 636, 0, - 0, 624, 1006, 0, 0, -2, -2, 381, 387, 388, - 389, 390, 366, 0, 393, 397, 0, 0, 0, 0, - 0, 62, 0, 978, 658, -2, -2, 0, 0, 701, - 702, -2, 839, -2, 707, 708, 709, 710, 711, 712, - 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, - 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, - 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, - 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, - 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, - 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, - 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, - 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, - 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, - 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, - 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, - 823, 824, 825, 0, 0, 95, 0, 93, 0, 1008, - 0, 0, 0, 0, 0, 0, 1008, 1008, 1008, 0, - 0, 0, 0, 267, 0, 0, 0, 0, 0, 0, - 0, 275, 0, 277, 1008, 321, 280, 0, 0, 1008, - 1008, 1008, 0, 1008, 1008, 287, 0, 288, 289, 0, - 197, 198, 199, 293, 1009, 1010, 1008, 1008, 295, 0, - 318, 316, 317, 308, 309, 0, 324, 302, 303, 306, - 307, 338, 341, 358, 356, 357, 359, 351, 352, 353, - 354, 0, 362, 363, 0, 0, 0, 0, 0, 461, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 485, - 486, 487, 488, 489, 490, 491, 464, 0, 478, 0, - 0, 0, 520, 521, 522, 523, 524, 525, 526, 527, - 528, 0, 378, 0, 0, 0, 624, 0, 0, 0, - 0, 0, 0, 0, 375, 0, 598, 0, 551, 559, - 0, 552, 560, 553, 561, 554, 0, 555, 562, 556, - 563, 557, 558, 564, 0, 0, 0, 378, 378, 0, - 0, 632, 0, 380, 34, 0, 0, 633, 625, 626, - 629, 632, 0, 402, 391, 382, 385, 386, 368, 0, - 394, 398, 0, 400, 401, 0, 0, 60, 0, 446, - 0, 404, 406, 407, 408, 428, 0, 430, 0, 0, - 0, 56, 58, 447, 0, 978, 664, 0, 64, 65, - 0, 0, 0, 173, 668, 669, 670, 666, 222, 0, - 0, 161, 157, 101, 102, 103, 150, 105, 150, 150, - 150, 150, 170, 170, 170, 170, 133, 134, 135, 136, - 137, 0, 0, 120, 150, 150, 150, 124, 140, 141, - 142, 143, 144, 145, 146, 147, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 152, 152, 152, 154, 154, - 697, 79, 0, 1008, 0, 1008, 91, 0, 236, 238, - 239, 0, 0, 0, 0, 0, 0, 0, 0, 270, - 674, 0, 1008, 273, 274, 448, 705, 706, 278, 279, - 322, 323, 281, 282, 283, 284, 285, 286, 325, 0, - 200, 201, 294, 298, 0, 321, 0, 0, 300, 301, - 0, 0, 339, 343, 344, 345, 346, 499, 458, 459, - 460, 462, 479, 0, 481, 483, 469, 470, 494, 495, - 496, 0, 0, 0, 0, 492, 474, 0, 505, 506, - 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, - 519, 582, 583, 0, 517, 518, 529, 0, 0, 0, - 379, 607, 0, -2, 0, 497, 653, 632, 0, 0, - 0, 0, 502, 609, 0, 502, 609, 0, 0, 0, - 376, 377, 604, 601, 0, 0, 606, 0, 568, 0, - 0, 0, 0, 0, 0, 0, 0, 636, 44, 637, - 0, 0, 0, 0, 628, 630, 631, 636, 0, 617, - 0, 0, 455, 0, 0, 383, 40, 399, 395, 0, - 455, 0, 0, 445, 0, 0, 0, 0, 0, 0, - 435, 0, 0, 438, 0, 0, 0, 0, 429, 0, - 0, 0, 450, 922, 431, 0, 433, 434, -2, 0, - 0, 0, 54, 55, 0, 0, 0, 659, 63, 0, - 0, 68, 69, 660, 661, 662, 663, 0, 92, 223, - 225, 228, 229, 230, 96, 97, 98, 0, 0, 210, - 0, 0, 204, 204, 0, 202, 203, 94, 164, 162, - 0, 159, 158, 104, 0, 170, 170, 127, 128, 173, - 0, 173, 173, 173, 0, 0, 121, 122, 123, 115, - 0, 116, 117, 118, 0, 119, 0, 0, 1008, 81, - 676, 82, 1007, 0, 0, 689, 237, 679, 680, 681, - 682, 683, 684, 685, 686, 687, 688, 0, 83, 241, - 243, 242, 246, 0, 0, 0, 268, 1008, 272, 318, - 318, 297, 319, 320, 304, 335, 480, 482, 484, 471, - 492, 475, 0, 472, 0, 0, 466, 534, 0, 0, - 378, 0, 624, 636, 538, 539, 0, 0, 0, 0, - 0, 575, 0, 0, 576, 0, 624, 0, 602, 0, - 0, 550, 0, 569, 0, 0, 570, 571, 572, 573, - 574, 36, 0, 634, 635, 627, 35, 0, 671, 672, - 618, 619, 620, 0, 392, 403, 384, 0, 632, 647, - 0, 0, 640, 0, 0, 455, 655, 0, 405, 424, - 426, 0, 421, 436, 437, 439, 0, 441, 0, 443, - 444, 409, 410, 411, 0, 412, 0, 0, 0, 0, - 432, 455, 0, 455, 57, 455, 59, 0, 449, 66, - 67, 0, 0, 73, 174, 175, 0, 226, 0, 0, - 0, 192, 204, 204, 195, 205, 196, 0, 166, 0, - 163, 100, 160, 0, 173, 173, 129, 0, 130, 131, - 132, 0, 148, 0, 0, 0, 0, 698, 80, 231, - 1007, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 1007, 0, 1007, 690, 691, - 692, 693, 0, 86, 0, 0, 0, 0, 0, 271, - 321, 321, 473, 0, 493, 476, 535, 536, 0, 608, - 632, 38, 0, 150, 150, 587, 150, 154, 590, 150, - 592, 150, 595, 0, 0, 0, 0, 0, 0, 0, - 599, 549, 605, 0, 607, 0, 0, 638, 37, 622, - 0, 456, 396, 41, 45, 0, 647, 639, 649, 651, - 0, 0, 643, 0, 416, 624, 0, 0, 418, 425, - 0, 0, 419, 0, 420, 440, 442, -2, 0, 0, - 0, 0, 624, 455, 52, 53, 0, 70, 71, 72, - 224, 227, 0, 206, 150, 209, 193, 194, 0, 168, - 0, 165, 151, 125, 126, 171, 172, 170, 0, 170, - 0, 155, 0, 1008, 232, 233, 234, 235, 0, 240, - 0, 84, 85, 0, 0, 245, 269, 291, 296, 477, - 537, 636, 540, 584, 170, 588, 589, 591, 593, 594, - 596, 542, 541, 0, 0, 0, 0, 0, 632, 0, - 603, 0, 0, 42, 0, 0, 0, 46, 0, 652, - 0, 0, 0, 61, 0, 632, 656, 657, 422, 0, - 427, 0, 0, 0, 430, 632, 51, 184, 0, 208, - 0, 414, 176, 169, 0, 173, 149, 173, 0, 0, - 78, 0, 87, 88, 0, 0, 0, 39, 585, 586, - 0, 0, 0, 0, 577, 0, 600, 0, 0, 623, - 621, 0, 650, 0, 642, 645, 644, 417, 49, 0, - 0, 452, 0, 0, 450, 50, 183, 185, 0, 190, - 0, 207, 0, 0, 181, 0, 178, 180, 167, 138, - 139, 153, 156, 0, 0, 0, 0, 247, 543, 545, - 544, 546, 0, 0, 0, 548, 565, 566, 0, 641, - 0, 423, 451, 453, 454, 413, 186, 187, 0, 191, - 189, 0, 415, 99, 0, 177, 179, 0, 263, 0, - 89, 90, 83, 547, 0, 0, 0, 648, 646, 188, - 0, 182, 262, 0, 0, 86, 578, 0, 581, 0, - 264, 0, 244, 579, 0, 0, 0, 211, 0, 0, - 212, 213, 0, 0, 580, 214, 0, 0, 0, 0, - 0, 215, 217, 218, 0, 0, 216, 265, 266, 219, - 220, 221, + 0, 624, 1009, 0, 0, -2, -2, 381, 387, 388, + 389, 390, 366, 0, 393, 397, 0, 0, 0, 678, + 0, 0, 62, 0, 981, 658, -2, -2, 0, 0, + 704, 705, -2, 842, -2, 710, 711, 712, 713, 714, + 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, + 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, + 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, + 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, + 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, + 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, + 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, + 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, + 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, + 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, + 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, + 825, 826, 827, 828, 0, 0, 95, 0, 93, 0, + 1011, 0, 0, 0, 0, 0, 0, 1011, 1011, 1011, + 0, 0, 0, 0, 690, 267, 0, 0, 0, 0, + 0, 0, 0, 275, 0, 277, 1011, 321, 280, 0, + 0, 1011, 1011, 1011, 0, 1011, 1011, 287, 0, 288, + 289, 0, 197, 198, 199, 293, 1012, 1013, 1011, 1011, + 295, 0, 318, 316, 317, 308, 309, 0, 324, 302, + 303, 306, 307, 338, 341, 358, 356, 357, 359, 351, + 352, 353, 354, 0, 362, 363, 0, 0, 0, 0, + 0, 461, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 485, 486, 487, 488, 489, 490, 491, 464, 0, + 478, 0, 0, 0, 520, 521, 522, 523, 524, 525, + 526, 527, 528, 0, 378, 0, 0, 0, 624, 0, + 0, 0, 0, 0, 0, 0, 375, 0, 598, 0, + 551, 559, 0, 552, 560, 553, 561, 554, 0, 555, + 562, 556, 563, 557, 558, 564, 0, 0, 0, 378, + 378, 0, 0, 632, 0, 380, 34, 0, 0, 633, + 625, 626, 629, 632, 0, 402, 391, 382, 385, 386, + 368, 0, 394, 398, 0, 400, 401, 0, 0, 60, + 0, 446, 0, 404, 406, 407, 408, 428, 0, 430, + 0, 0, 0, 56, 58, 447, 0, 981, 664, 0, + 64, 65, 0, 0, 0, 173, 668, 669, 670, 666, + 222, 0, 0, 161, 157, 101, 102, 103, 150, 105, + 150, 150, 150, 150, 170, 170, 170, 170, 133, 134, + 135, 136, 137, 0, 0, 120, 150, 150, 150, 124, + 140, 141, 142, 143, 144, 145, 146, 147, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 152, 152, 152, + 154, 154, 700, 79, 0, 1011, 0, 1011, 91, 0, + 236, 238, 239, 0, 0, 0, 0, 0, 0, 691, + 0, 0, 270, 674, 0, 1011, 273, 274, 448, 708, + 709, 278, 279, 322, 323, 281, 282, 283, 284, 285, + 286, 325, 0, 200, 201, 294, 298, 0, 321, 0, + 0, 300, 301, 0, 0, 339, 343, 344, 345, 346, + 499, 458, 459, 460, 462, 479, 0, 481, 483, 469, + 470, 494, 495, 496, 0, 0, 0, 0, 492, 474, + 0, 505, 506, 507, 508, 509, 510, 511, 512, 513, + 514, 515, 516, 519, 582, 583, 0, 517, 518, 529, + 0, 0, 0, 379, 607, 0, -2, 0, 497, 653, + 632, 0, 0, 0, 0, 502, 609, 0, 502, 609, + 0, 0, 0, 376, 377, 604, 601, 0, 0, 606, + 0, 568, 0, 0, 0, 0, 0, 0, 0, 0, + 636, 44, 637, 0, 0, 0, 0, 628, 630, 631, + 636, 0, 617, 0, 0, 455, 0, 0, 383, 40, + 399, 395, 0, 455, 0, 0, 445, 0, 0, 0, + 0, 0, 0, 435, 0, 0, 438, 0, 0, 0, + 0, 429, 0, 0, 0, 450, 925, 431, 0, 433, + 434, -2, 0, 0, 0, 54, 55, 0, 0, 0, + 659, 63, 0, 0, 68, 69, 660, 661, 662, 663, + 0, 92, 223, 225, 228, 229, 230, 96, 97, 98, + 0, 0, 210, 0, 0, 204, 204, 0, 202, 203, + 94, 164, 162, 0, 159, 158, 104, 0, 170, 170, + 127, 128, 173, 0, 173, 173, 173, 0, 0, 121, + 122, 123, 115, 0, 116, 117, 118, 0, 119, 0, + 0, 1011, 81, 676, 82, 1010, 0, 0, 692, 237, + 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, + 0, 83, 241, 243, 242, 246, 0, 0, 0, 268, + 1011, 272, 318, 318, 297, 319, 320, 304, 335, 480, + 482, 484, 471, 492, 475, 0, 472, 0, 0, 466, + 534, 0, 0, 378, 0, 624, 636, 538, 539, 0, + 0, 0, 0, 0, 575, 0, 0, 576, 0, 624, + 0, 602, 0, 0, 550, 0, 569, 0, 0, 570, + 571, 572, 573, 574, 36, 0, 634, 635, 627, 35, + 0, 671, 672, 618, 619, 620, 0, 392, 403, 384, + 0, 632, 647, 0, 0, 640, 0, 0, 455, 655, + 0, 405, 424, 426, 0, 421, 436, 437, 439, 0, + 441, 0, 443, 444, 409, 410, 411, 0, 412, 0, + 0, 0, 0, 432, 455, 0, 455, 57, 455, 59, + 0, 449, 66, 67, 0, 0, 73, 174, 175, 0, + 226, 0, 0, 0, 192, 204, 204, 195, 205, 196, + 0, 166, 0, 163, 100, 160, 0, 173, 173, 129, + 0, 130, 131, 132, 0, 148, 0, 0, 0, 0, + 701, 80, 231, 1010, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 1010, 0, + 1010, 693, 694, 695, 696, 0, 86, 0, 0, 0, + 0, 0, 271, 321, 321, 473, 0, 493, 476, 535, + 536, 0, 608, 632, 38, 0, 150, 150, 587, 150, + 154, 590, 150, 592, 150, 595, 0, 0, 0, 0, + 0, 0, 0, 599, 549, 605, 0, 607, 0, 0, + 638, 37, 622, 0, 456, 396, 41, 45, 0, 647, + 639, 649, 651, 0, 0, 643, 0, 416, 624, 0, + 0, 418, 425, 0, 0, 419, 0, 420, 440, 442, + -2, 0, 0, 0, 0, 624, 455, 52, 53, 0, + 70, 71, 72, 224, 227, 0, 206, 150, 209, 193, + 194, 0, 168, 0, 165, 151, 125, 126, 171, 172, + 170, 0, 170, 0, 155, 0, 1011, 232, 233, 234, + 235, 0, 240, 0, 84, 85, 0, 0, 245, 269, + 291, 296, 477, 537, 636, 540, 584, 170, 588, 589, + 591, 593, 594, 596, 542, 541, 0, 0, 0, 0, + 0, 632, 0, 603, 0, 0, 42, 0, 0, 0, + 46, 0, 652, 0, 0, 0, 61, 0, 632, 656, + 657, 422, 0, 427, 0, 0, 0, 430, 632, 51, + 184, 0, 208, 0, 414, 176, 169, 0, 173, 149, + 173, 0, 0, 78, 0, 87, 88, 0, 0, 0, + 39, 585, 586, 0, 0, 0, 0, 577, 0, 600, + 0, 0, 623, 621, 0, 650, 0, 642, 645, 644, + 417, 49, 0, 0, 452, 0, 0, 450, 50, 183, + 185, 0, 190, 0, 207, 0, 0, 181, 0, 178, + 180, 167, 138, 139, 153, 156, 0, 0, 0, 0, + 247, 543, 545, 544, 546, 0, 0, 0, 548, 565, + 566, 0, 641, 0, 423, 451, 453, 454, 413, 186, + 187, 0, 191, 189, 0, 415, 99, 0, 177, 179, + 0, 263, 0, 89, 90, 83, 547, 0, 0, 0, + 648, 646, 188, 0, 182, 262, 0, 0, 86, 578, + 0, 581, 0, 264, 0, 244, 579, 0, 0, 0, + 211, 0, 0, 212, 213, 0, 0, 580, 214, 0, + 0, 0, 0, 0, 215, 217, 218, 0, 0, 216, + 265, 266, 219, 220, 221, } var yyTok1 = [...]int{ @@ -3795,59 +3848,59 @@ yydefault: case 1: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:357 +//line sql.y:359 { setParseTree(yylex, yyDollar[1].statement) } case 2: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:362 +//line sql.y:364 { } case 3: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:363 +//line sql.y:365 { } case 4: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:367 +//line sql.y:369 { yyVAL.statement = yyDollar[1].selStmt } case 29: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:395 +//line sql.y:397 { setParseTree(yylex, nil) } case 30: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:401 +//line sql.y:403 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), NoAt) } case 31: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:405 +//line sql.y:407 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), SingleAt) } case 32: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:409 +//line sql.y:411 { yyVAL.colIdent = NewColIdentWithAt(string(yyDollar[1].bytes), DoubleAt) } case 33: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:415 +//line sql.y:417 { yyVAL.statement = &OtherAdmin{} } case 34: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:421 +//line sql.y:423 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -3857,25 +3910,25 @@ yydefault: } case 35: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:429 +//line sql.y:431 { yyVAL.selStmt = &Union{FirstStatement: &ParenSelect{Select: yyDollar[2].selStmt}, OrderBy: yyDollar[4].orderBy, Limit: yyDollar[5].limit, Lock: yyDollar[6].lock} } case 36: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:433 +//line sql.y:435 { yyVAL.selStmt = Unionize(yyDollar[1].selStmt, yyDollar[3].selStmt, yyDollar[2].unionType, yyDollar[4].orderBy, yyDollar[5].limit, yyDollar[6].lock) } case 37: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:437 +//line sql.y:439 { yyVAL.selStmt = NewSelect(Comments(yyDollar[2].bytes2), SelectExprs{Nextval{Expr: yyDollar[5].expr}}, []string{yyDollar[3].str} /*options*/, TableExprs{&AliasedTableExpr{Expr: yyDollar[7].tableName}}, nil /*where*/, nil /*groupBy*/, nil /*having*/) } case 38: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:460 +//line sql.y:462 { sel := yyDollar[1].selStmt.(*Select) sel.OrderBy = yyDollar[2].orderBy @@ -3885,43 +3938,43 @@ yydefault: } case 39: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:468 +//line sql.y:470 { yyVAL.selStmt = Unionize(yyDollar[1].selStmt, yyDollar[3].selStmt, yyDollar[2].unionType, yyDollar[4].orderBy, yyDollar[5].limit, yyDollar[6].lock) } case 40: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:474 +//line sql.y:476 { yyVAL.statement = &Stream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName} } case 41: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:480 +//line sql.y:482 { yyVAL.statement = &VStream{Comments: Comments(yyDollar[2].bytes2), SelectExpr: yyDollar[3].selectExpr, Table: yyDollar[5].tableName, Where: NewWhere(WhereClause, yyDollar[6].expr), Limit: yyDollar[7].limit} } case 42: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:488 +//line sql.y:490 { yyVAL.selStmt = NewSelect(Comments(yyDollar[2].bytes2), yyDollar[4].selectExprs /*SelectExprs*/, yyDollar[3].strs /*options*/, yyDollar[5].tableExprs /*from*/, NewWhere(WhereClause, yyDollar[6].expr), GroupBy(yyDollar[7].exprs), NewWhere(HavingClause, yyDollar[8].expr)) } case 43: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:494 +//line sql.y:496 { yyVAL.selStmt = yyDollar[1].selStmt } case 44: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:498 +//line sql.y:500 { yyVAL.selStmt = &ParenSelect{Select: yyDollar[2].selStmt} } case 45: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:505 +//line sql.y:507 { // insert_data returns a *Insert pre-filled with Columns & Values ins := yyDollar[6].ins @@ -3935,7 +3988,7 @@ yydefault: } case 46: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:517 +//line sql.y:519 { cols := make(Columns, 0, len(yyDollar[7].updateExprs)) vals := make(ValTuple, 0, len(yyDollar[8].updateExprs)) @@ -3947,186 +4000,186 @@ yydefault: } case 47: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:529 +//line sql.y:531 { yyVAL.insertAction = InsertAct } case 48: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:533 +//line sql.y:535 { yyVAL.insertAction = ReplaceAct } case 49: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:539 +//line sql.y:541 { yyVAL.statement = &Update{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, TableExprs: yyDollar[4].tableExprs, Exprs: yyDollar[6].updateExprs, Where: NewWhere(WhereClause, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } case 50: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:545 +//line sql.y:547 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, TableExprs: TableExprs{&AliasedTableExpr{Expr: yyDollar[5].tableName}}, Partitions: yyDollar[6].partitions, Where: NewWhere(WhereClause, yyDollar[7].expr), OrderBy: yyDollar[8].orderBy, Limit: yyDollar[9].limit} } case 51: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:549 +//line sql.y:551 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[5].tableNames, TableExprs: yyDollar[7].tableExprs, Where: NewWhere(WhereClause, yyDollar[8].expr)} } case 52: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:553 +//line sql.y:555 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereClause, yyDollar[7].expr)} } case 53: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:557 +//line sql.y:559 { yyVAL.statement = &Delete{Comments: Comments(yyDollar[2].bytes2), Ignore: yyDollar[3].ignore, Targets: yyDollar[4].tableNames, TableExprs: yyDollar[6].tableExprs, Where: NewWhere(WhereClause, yyDollar[7].expr)} } case 54: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:562 +//line sql.y:564 { } case 55: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:563 +//line sql.y:565 { } case 56: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:567 +//line sql.y:569 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 57: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:571 +//line sql.y:573 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } case 58: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:577 +//line sql.y:579 { yyVAL.tableNames = TableNames{yyDollar[1].tableName} } case 59: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:581 +//line sql.y:583 { yyVAL.tableNames = append(yyVAL.tableNames, yyDollar[3].tableName) } case 60: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:586 +//line sql.y:588 { yyVAL.partitions = nil } case 61: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:590 +//line sql.y:592 { yyVAL.partitions = yyDollar[3].partitions } case 62: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:596 +//line sql.y:598 { yyVAL.statement = &Set{Comments: Comments(yyDollar[2].bytes2), Exprs: yyDollar[3].setExprs} } case 63: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:602 +//line sql.y:604 { yyVAL.statement = &SetTransaction{Comments: Comments(yyDollar[2].bytes2), Scope: yyDollar[3].scope, Characteristics: yyDollar[5].characteristics} } case 64: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:606 +//line sql.y:608 { yyVAL.statement = &SetTransaction{Comments: Comments(yyDollar[2].bytes2), Characteristics: yyDollar[4].characteristics, Scope: ImplicitScope} } case 65: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:612 +//line sql.y:614 { yyVAL.characteristics = []Characteristic{yyDollar[1].characteristic} } case 66: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:616 +//line sql.y:618 { yyVAL.characteristics = append(yyVAL.characteristics, yyDollar[3].characteristic) } case 67: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:622 +//line sql.y:624 { yyVAL.characteristic = yyDollar[3].isolationLevel } case 68: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:626 +//line sql.y:628 { yyVAL.characteristic = ReadWrite } case 69: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:630 +//line sql.y:632 { yyVAL.characteristic = ReadOnly } case 70: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:636 +//line sql.y:638 { yyVAL.isolationLevel = RepeatableRead } case 71: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:640 +//line sql.y:642 { yyVAL.isolationLevel = ReadCommitted } case 72: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:644 +//line sql.y:646 { yyVAL.isolationLevel = ReadUncommitted } case 73: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:648 +//line sql.y:650 { yyVAL.isolationLevel = Serializable } case 74: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:654 +//line sql.y:656 { yyVAL.scope = SessionScope } case 75: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:658 +//line sql.y:660 { yyVAL.scope = GlobalScope } case 76: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:664 +//line sql.y:666 { yyDollar[1].ddl.TableSpec = yyDollar[2].TableSpec yyVAL.statement = yyDollar[1].ddl } case 77: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:669 +//line sql.y:671 { // Create table [name] like [name] yyDollar[1].ddl.OptLike = yyDollar[2].optLike @@ -4134,139 +4187,139 @@ yydefault: } case 78: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:675 +//line sql.y:677 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[7].tableName} } case 79: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:680 +//line sql.y:682 { yyVAL.statement = &DDL{Action: CreateDDLAction, Table: yyDollar[3].tableName.ToViewName()} } case 80: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:684 +//line sql.y:686 { yyVAL.statement = &DDL{Action: CreateDDLAction, Table: yyDollar[5].tableName.ToViewName()} } case 81: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:688 +//line sql.y:690 { yyVAL.statement = &DBDDL{Action: CreateDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfNotExists: yyDollar[3].boolean} } case 82: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:692 +//line sql.y:694 { yyVAL.statement = &DBDDL{Action: CreateDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfNotExists: yyDollar[3].boolean} } case 83: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:697 +//line sql.y:699 { yyVAL.colIdent = NewColIdent("") } case 84: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:701 +//line sql.y:703 { yyVAL.colIdent = yyDollar[2].colIdent } case 85: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:707 +//line sql.y:709 { yyVAL.colIdent = yyDollar[1].colIdent } case 86: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:712 +//line sql.y:714 { var v []VindexParam yyVAL.vindexParams = v } case 87: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:717 +//line sql.y:719 { yyVAL.vindexParams = yyDollar[2].vindexParams } case 88: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:723 +//line sql.y:725 { yyVAL.vindexParams = make([]VindexParam, 0, 4) yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[1].vindexParam) } case 89: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:728 +//line sql.y:730 { yyVAL.vindexParams = append(yyVAL.vindexParams, yyDollar[3].vindexParam) } case 90: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:734 +//line sql.y:736 { yyVAL.vindexParam = VindexParam{Key: yyDollar[1].colIdent, Val: yyDollar[3].str} } case 91: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:740 +//line sql.y:742 { yyVAL.ddl = &DDL{Action: CreateDDLAction, Table: yyDollar[4].tableName} setDDL(yylex, yyVAL.ddl) } case 92: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:747 +//line sql.y:749 { yyVAL.TableSpec = yyDollar[2].TableSpec yyVAL.TableSpec.Options = yyDollar[4].str } case 93: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:754 +//line sql.y:756 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[2].tableName} } case 94: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:758 +//line sql.y:760 { yyVAL.optLike = &OptLike{LikeTable: yyDollar[3].tableName} } case 95: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:764 +//line sql.y:766 { yyVAL.TableSpec = &TableSpec{} yyVAL.TableSpec.AddColumn(yyDollar[1].columnDefinition) } case 96: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:769 +//line sql.y:771 { yyVAL.TableSpec.AddColumn(yyDollar[3].columnDefinition) } case 97: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:773 +//line sql.y:775 { yyVAL.TableSpec.AddIndex(yyDollar[3].indexDefinition) } case 98: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:777 +//line sql.y:779 { yyVAL.TableSpec.AddConstraint(yyDollar[3].constraintDefinition) } case 99: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:783 +//line sql.y:785 { yyDollar[2].columnType.NotNull = yyDollar[3].boolean yyDollar[2].columnType.Default = yyDollar[4].optVal @@ -4278,7 +4331,7 @@ yydefault: } case 100: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:794 +//line sql.y:796 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Unsigned = yyDollar[2].boolean @@ -4286,74 +4339,74 @@ yydefault: } case 104: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:805 +//line sql.y:807 { yyVAL.columnType = yyDollar[1].columnType yyVAL.columnType.Length = yyDollar[2].literal } case 105: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:810 +//line sql.y:812 { yyVAL.columnType = yyDollar[1].columnType } case 106: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:816 +//line sql.y:818 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 107: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:820 +//line sql.y:822 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 108: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:824 +//line sql.y:826 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 109: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:828 +//line sql.y:830 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 110: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:832 +//line sql.y:834 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 111: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:836 +//line sql.y:838 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 112: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:840 +//line sql.y:842 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 113: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:844 +//line sql.y:846 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 114: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:848 +//line sql.y:850 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 115: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:854 +//line sql.y:856 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4361,7 +4414,7 @@ yydefault: } case 116: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:860 +//line sql.y:862 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4369,7 +4422,7 @@ yydefault: } case 117: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:866 +//line sql.y:868 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4377,7 +4430,7 @@ yydefault: } case 118: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:872 +//line sql.y:874 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4385,7 +4438,7 @@ yydefault: } case 119: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:878 +//line sql.y:880 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} yyVAL.columnType.Length = yyDollar[2].LengthScaleOption.Length @@ -4393,206 +4446,206 @@ yydefault: } case 120: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:886 +//line sql.y:888 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 121: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:890 +//line sql.y:892 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 122: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:894 +//line sql.y:896 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 123: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:898 +//line sql.y:900 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 124: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:902 +//line sql.y:904 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 125: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:908 +//line sql.y:910 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 126: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:912 +//line sql.y:914 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Collate: yyDollar[4].str} } case 127: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:916 +//line sql.y:918 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 128: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:920 +//line sql.y:922 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 129: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:924 +//line sql.y:926 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 130: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:928 +//line sql.y:930 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 131: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:932 +//line sql.y:934 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 132: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:936 +//line sql.y:938 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), Charset: yyDollar[2].str, Collate: yyDollar[3].str} } case 133: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:940 +//line sql.y:942 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 134: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:944 +//line sql.y:946 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 135: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:948 +//line sql.y:950 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 136: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:952 +//line sql.y:954 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 137: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:956 +//line sql.y:958 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 138: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:960 +//line sql.y:962 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 139: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:965 +//line sql.y:967 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes), EnumValues: yyDollar[3].strs, Charset: yyDollar[5].str, Collate: yyDollar[6].str} } case 140: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:971 +//line sql.y:973 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 141: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:975 +//line sql.y:977 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 142: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:979 +//line sql.y:981 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 143: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:983 +//line sql.y:985 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 144: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:987 +//line sql.y:989 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 145: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:991 +//line sql.y:993 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 146: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:995 +//line sql.y:997 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 147: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:999 +//line sql.y:1001 { yyVAL.columnType = ColumnType{Type: string(yyDollar[1].bytes)} } case 148: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1005 +//line sql.y:1007 { yyVAL.strs = make([]string, 0, 4) yyVAL.strs = append(yyVAL.strs, "'"+string(yyDollar[1].bytes)+"'") } case 149: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1010 +//line sql.y:1012 { yyVAL.strs = append(yyDollar[1].strs, "'"+string(yyDollar[3].bytes)+"'") } case 150: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1015 +//line sql.y:1017 { yyVAL.literal = nil } case 151: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1019 +//line sql.y:1021 { yyVAL.literal = NewIntLiteral(yyDollar[2].bytes) } case 152: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1024 +//line sql.y:1026 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 153: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1028 +//line sql.y:1030 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), @@ -4601,13 +4654,13 @@ yydefault: } case 154: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1036 +//line sql.y:1038 { yyVAL.LengthScaleOption = LengthScaleOption{} } case 155: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1040 +//line sql.y:1042 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), @@ -4615,7 +4668,7 @@ yydefault: } case 156: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1046 +//line sql.y:1048 { yyVAL.LengthScaleOption = LengthScaleOption{ Length: NewIntLiteral(yyDollar[2].bytes), @@ -4624,508 +4677,508 @@ yydefault: } case 157: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1054 +//line sql.y:1056 { yyVAL.boolean = false } case 158: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1058 +//line sql.y:1060 { yyVAL.boolean = true } case 159: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1063 +//line sql.y:1065 { yyVAL.boolean = false } case 160: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1067 +//line sql.y:1069 { yyVAL.boolean = true } case 161: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1073 +//line sql.y:1075 { yyVAL.boolean = false } case 162: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1077 +//line sql.y:1079 { yyVAL.boolean = false } case 163: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1081 +//line sql.y:1083 { yyVAL.boolean = true } case 164: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1086 +//line sql.y:1088 { yyVAL.optVal = nil } case 165: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1090 +//line sql.y:1092 { yyVAL.optVal = yyDollar[2].expr } case 166: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1095 +//line sql.y:1097 { yyVAL.optVal = nil } case 167: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1099 +//line sql.y:1101 { yyVAL.optVal = yyDollar[3].expr } case 168: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1104 +//line sql.y:1106 { yyVAL.boolean = false } case 169: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1108 +//line sql.y:1110 { yyVAL.boolean = true } case 170: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1113 +//line sql.y:1115 { yyVAL.str = "" } case 171: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1117 +//line sql.y:1119 { yyVAL.str = string(yyDollar[3].colIdent.String()) } case 172: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1121 +//line sql.y:1123 { yyVAL.str = string(yyDollar[3].bytes) } case 173: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1126 +//line sql.y:1128 { yyVAL.str = "" } case 174: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1130 +//line sql.y:1132 { yyVAL.str = string(yyDollar[2].colIdent.String()) } case 175: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1134 +//line sql.y:1136 { yyVAL.str = string(yyDollar[2].bytes) } case 176: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1139 +//line sql.y:1141 { yyVAL.colKeyOpt = colKeyNone } case 177: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1143 +//line sql.y:1145 { yyVAL.colKeyOpt = colKeyPrimary } case 178: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1147 +//line sql.y:1149 { yyVAL.colKeyOpt = colKey } case 179: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1151 +//line sql.y:1153 { yyVAL.colKeyOpt = colKeyUniqueKey } case 180: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1155 +//line sql.y:1157 { yyVAL.colKeyOpt = colKeyUnique } case 181: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1160 +//line sql.y:1162 { yyVAL.literal = nil } case 182: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1164 +//line sql.y:1166 { yyVAL.literal = NewStrLiteral(yyDollar[2].bytes) } case 183: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1170 +//line sql.y:1172 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns, Options: yyDollar[5].indexOptions} } case 184: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1174 +//line sql.y:1176 { yyVAL.indexDefinition = &IndexDefinition{Info: yyDollar[1].indexInfo, Columns: yyDollar[3].indexColumns} } case 185: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1180 +//line sql.y:1182 { yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } case 186: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1184 +//line sql.y:1186 { yyVAL.indexOptions = append(yyVAL.indexOptions, yyDollar[2].indexOption) } case 187: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1190 +//line sql.y:1192 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Using: string(yyDollar[2].colIdent.String())} } case 188: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1194 +//line sql.y:1196 { // should not be string yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewIntLiteral(yyDollar[3].bytes)} } case 189: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1199 +//line sql.y:1201 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), Value: NewStrLiteral(yyDollar[2].bytes)} } case 190: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1205 +//line sql.y:1207 { yyVAL.str = "" } case 191: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1209 +//line sql.y:1211 { yyVAL.str = string(yyDollar[1].bytes) } case 192: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1215 +//line sql.y:1217 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].bytes), Name: NewColIdent("PRIMARY"), Primary: true, Unique: true} } case 193: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1219 +//line sql.y:1221 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Spatial: true, Unique: false} } case 194: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1223 +//line sql.y:1225 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes) + " " + string(yyDollar[2].str), Name: NewColIdent(yyDollar[3].str), Unique: true} } case 195: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1227 +//line sql.y:1229 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].bytes), Name: NewColIdent(yyDollar[2].str), Unique: true} } case 196: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1231 +//line sql.y:1233 { yyVAL.indexInfo = &IndexInfo{Type: string(yyDollar[1].str), Name: NewColIdent(yyDollar[2].str), Unique: false} } case 197: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1237 +//line sql.y:1239 { yyVAL.str = string(yyDollar[1].bytes) } case 198: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1241 +//line sql.y:1243 { yyVAL.str = string(yyDollar[1].bytes) } case 199: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1245 +//line sql.y:1247 { yyVAL.str = string(yyDollar[1].bytes) } case 200: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1252 +//line sql.y:1254 { yyVAL.str = string(yyDollar[1].bytes) } case 201: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1256 +//line sql.y:1258 { yyVAL.str = string(yyDollar[1].bytes) } case 202: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1262 +//line sql.y:1264 { yyVAL.str = string(yyDollar[1].bytes) } case 203: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1266 +//line sql.y:1268 { yyVAL.str = string(yyDollar[1].bytes) } case 204: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1271 +//line sql.y:1273 { yyVAL.str = "" } case 205: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1275 +//line sql.y:1277 { yyVAL.str = string(yyDollar[1].colIdent.String()) } case 206: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1281 +//line sql.y:1283 { yyVAL.indexColumns = []*IndexColumn{yyDollar[1].indexColumn} } case 207: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1285 +//line sql.y:1287 { yyVAL.indexColumns = append(yyVAL.indexColumns, yyDollar[3].indexColumn) } case 208: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1291 +//line sql.y:1293 { yyVAL.indexColumn = &IndexColumn{Column: yyDollar[1].colIdent, Length: yyDollar[2].literal} } case 209: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1297 +//line sql.y:1299 { yyVAL.constraintDefinition = &ConstraintDefinition{Name: string(yyDollar[2].colIdent.String()), Details: yyDollar[3].constraintInfo} } case 210: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1301 +//line sql.y:1303 { yyVAL.constraintDefinition = &ConstraintDefinition{Details: yyDollar[1].constraintInfo} } case 211: yyDollar = yyS[yypt-10 : yypt+1] -//line sql.y:1308 +//line sql.y:1310 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns} } case 212: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1312 +//line sql.y:1314 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction} } case 213: yyDollar = yyS[yypt-11 : yypt+1] -//line sql.y:1316 +//line sql.y:1318 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnUpdate: yyDollar[11].ReferenceAction} } case 214: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1320 +//line sql.y:1322 { yyVAL.constraintInfo = &ForeignKeyDefinition{Source: yyDollar[4].columns, ReferencedTable: yyDollar[7].tableName, ReferencedColumns: yyDollar[9].columns, OnDelete: yyDollar[11].ReferenceAction, OnUpdate: yyDollar[12].ReferenceAction} } case 215: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1326 +//line sql.y:1328 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } case 216: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1332 +//line sql.y:1334 { yyVAL.ReferenceAction = yyDollar[3].ReferenceAction } case 217: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1338 +//line sql.y:1340 { yyVAL.ReferenceAction = Restrict } case 218: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1342 +//line sql.y:1344 { yyVAL.ReferenceAction = Cascade } case 219: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1346 +//line sql.y:1348 { yyVAL.ReferenceAction = NoAction } case 220: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1350 +//line sql.y:1352 { yyVAL.ReferenceAction = SetDefault } case 221: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1354 +//line sql.y:1356 { yyVAL.ReferenceAction = SetNull } case 222: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1359 +//line sql.y:1361 { yyVAL.str = "" } case 223: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1363 +//line sql.y:1365 { yyVAL.str = " " + string(yyDollar[1].str) } case 224: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1367 +//line sql.y:1369 { yyVAL.str = string(yyDollar[1].str) + ", " + string(yyDollar[3].str) } case 225: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1375 +//line sql.y:1377 { yyVAL.str = yyDollar[1].str } case 226: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1379 +//line sql.y:1381 { yyVAL.str = yyDollar[1].str + " " + yyDollar[2].str } case 227: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1383 +//line sql.y:1385 { yyVAL.str = yyDollar[1].str + "=" + yyDollar[3].str } case 228: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1389 +//line sql.y:1391 { yyVAL.str = yyDollar[1].colIdent.String() } case 229: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1393 +//line sql.y:1395 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'" } case 230: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1397 +//line sql.y:1399 { yyVAL.str = string(yyDollar[1].bytes) } case 231: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1403 +//line sql.y:1405 { - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} } case 232: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1407 +//line sql.y:1409 { - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} } case 233: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1411 +//line sql.y:1413 { - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} } case 234: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1415 +//line sql.y:1417 { // Change this to a rename statement yyVAL.statement = &DDL{Action: RenameDDLAction, FromTables: TableNames{yyDollar[4].tableName}, ToTables: TableNames{yyDollar[7].tableName}} } case 235: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1420 +//line sql.y:1422 { // Rename an index can just be an alter - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[4].tableName} + yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName} } case 236: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1425 +//line sql.y:1427 { yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[3].tableName.ToViewName()} } case 237: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1429 +//line sql.y:1431 { - yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} + yyVAL.statement = &DDL{Action: AlterDDLAction, OnlineHint: yyDollar[2].OnlineDDLHint, Table: yyDollar[4].tableName, PartitionSpec: yyDollar[5].partSpec} } case 238: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1433 +//line sql.y:1435 { yyVAL.statement = &DBDDL{Action: AlterDBDDLAction, DBName: string(yyDollar[3].colIdent.String())} } case 239: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1437 +//line sql.y:1439 { yyVAL.statement = &DBDDL{Action: AlterDBDDLAction, DBName: string(yyDollar[3].colIdent.String())} } case 240: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1441 +//line sql.y:1443 { yyVAL.statement = &DDL{ Action: CreateVindexDDLAction, @@ -5139,7 +5192,7 @@ yydefault: } case 241: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1453 +//line sql.y:1455 { yyVAL.statement = &DDL{ Action: DropVindexDDLAction, @@ -5151,19 +5204,19 @@ yydefault: } case 242: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1463 +//line sql.y:1465 { yyVAL.statement = &DDL{Action: AddVschemaTableDDLAction, Table: yyDollar[5].tableName} } case 243: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1467 +//line sql.y:1469 { yyVAL.statement = &DDL{Action: DropVschemaTableDDLAction, Table: yyDollar[5].tableName} } case 244: yyDollar = yyS[yypt-12 : yypt+1] -//line sql.y:1471 +//line sql.y:1473 { yyVAL.statement = &DDL{ Action: AddColVindexDDLAction, @@ -5178,7 +5231,7 @@ yydefault: } case 245: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1484 +//line sql.y:1486 { yyVAL.statement = &DDL{ Action: DropColVindexDDLAction, @@ -5190,13 +5243,13 @@ yydefault: } case 246: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1494 +//line sql.y:1496 { yyVAL.statement = &DDL{Action: AddSequenceDDLAction, Table: yyDollar[5].tableName} } case 247: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:1498 +//line sql.y:1500 { yyVAL.statement = &DDL{ Action: AddAutoIncDDLAction, @@ -5209,49 +5262,49 @@ yydefault: } case 262: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1527 +//line sql.y:1529 { yyVAL.partSpec = &PartitionSpec{Action: ReorganizeAction, Name: yyDollar[3].colIdent, Definitions: yyDollar[6].partDefs} } case 263: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1533 +//line sql.y:1535 { yyVAL.partDefs = []*PartitionDefinition{yyDollar[1].partDef} } case 264: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1537 +//line sql.y:1539 { yyVAL.partDefs = append(yyDollar[1].partDefs, yyDollar[3].partDef) } case 265: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1543 +//line sql.y:1545 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Limit: yyDollar[7].expr} } case 266: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:1547 +//line sql.y:1549 { yyVAL.partDef = &PartitionDefinition{Name: yyDollar[2].colIdent, Maxvalue: true} } case 267: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1553 +//line sql.y:1555 { yyVAL.statement = yyDollar[3].ddl } case 268: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1559 +//line sql.y:1561 { yyVAL.ddl = &DDL{Action: RenameDDLAction, FromTables: TableNames{yyDollar[1].tableName}, ToTables: TableNames{yyDollar[3].tableName}} } case 269: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1563 +//line sql.y:1565 { yyVAL.ddl = yyDollar[1].ddl yyVAL.ddl.FromTables = append(yyVAL.ddl.FromTables, yyDollar[3].tableName) @@ -5259,177 +5312,177 @@ yydefault: } case 270: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1571 +//line sql.y:1573 { yyVAL.statement = &DDL{Action: DropDDLAction, FromTables: yyDollar[4].tableNames, IfExists: yyDollar[3].boolean} } case 271: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:1575 +//line sql.y:1577 { // Change this to an alter statement yyVAL.statement = &DDL{Action: AlterDDLAction, Table: yyDollar[5].tableName} } case 272: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1580 +//line sql.y:1582 { yyVAL.statement = &DDL{Action: DropDDLAction, FromTables: TableNames{yyDollar[4].tableName.ToViewName()}, IfExists: yyDollar[3].boolean} } case 273: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1584 +//line sql.y:1586 { yyVAL.statement = &DBDDL{Action: DropDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfExists: yyDollar[3].boolean} } case 274: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1588 +//line sql.y:1590 { yyVAL.statement = &DBDDL{Action: DropDBDDLAction, DBName: string(yyDollar[4].colIdent.String()), IfExists: yyDollar[3].boolean} } case 275: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1594 +//line sql.y:1596 { yyVAL.statement = &DDL{Action: TruncateDDLAction, Table: yyDollar[3].tableName} } case 276: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1598 +//line sql.y:1600 { yyVAL.statement = &DDL{Action: TruncateDDLAction, Table: yyDollar[2].tableName} } case 277: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1603 +//line sql.y:1605 { yyVAL.statement = &OtherRead{} } case 278: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1609 +//line sql.y:1611 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].colIdent.String()), Scope: ImplicitScope} } case 279: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1614 +//line sql.y:1616 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{Type: CharsetStr, ShowTablesOpt: showTablesOpt, Scope: ImplicitScope} } case 280: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1619 +//line sql.y:1621 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope} } case 281: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1624 +//line sql.y:1626 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 282: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1629 +//line sql.y:1631 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].colIdent.String()), Scope: ImplicitScope} } case 283: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1633 +//line sql.y:1635 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 284: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1637 +//line sql.y:1639 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Table: yyDollar[4].tableName, Scope: ImplicitScope} } case 285: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1641 +//line sql.y:1643 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 286: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1645 +//line sql.y:1647 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 287: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1649 +//line sql.y:1651 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope} } case 288: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1654 +//line sql.y:1656 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope} } case 289: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1659 +//line sql.y:1661 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[3].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowTablesOpt: showTablesOpt, Scope: ImplicitScope} } case 290: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1664 +//line sql.y:1666 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 291: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1668 +//line sql.y:1670 { showTablesOpt := &ShowTablesOpt{DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter} yyVAL.statement = &Show{Extended: string(yyDollar[2].str), Type: string(yyDollar[3].str), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName, Scope: ImplicitScope} } case 292: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1673 +//line sql.y:1675 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 293: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1677 +//line sql.y:1679 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 294: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1681 +//line sql.y:1683 { yyVAL.statement = &Show{Scope: yyDollar[2].scope, Type: string(yyDollar[3].bytes)} } case 295: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1685 +//line sql.y:1687 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 296: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:1689 +//line sql.y:1691 { showTablesOpt := &ShowTablesOpt{Full: yyDollar[2].str, DbName: yyDollar[6].str, Filter: yyDollar[7].showFilter} yyVAL.statement = &Show{Type: string(yyDollar[3].str), ShowTablesOpt: showTablesOpt, OnTable: yyDollar[5].tableName, Scope: ImplicitScope} } case 297: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1694 +//line sql.y:1696 { // this is ugly, but I couldn't find a better way for now if yyDollar[3].str == "processlist" { @@ -5441,56 +5494,56 @@ yydefault: } case 298: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1704 +//line sql.y:1706 { yyVAL.statement = &Show{Scope: yyDollar[2].scope, Type: string(yyDollar[3].bytes)} } case 299: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1708 +//line sql.y:1710 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 300: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1712 +//line sql.y:1714 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), ShowCollationFilterOpt: yyDollar[4].expr, Scope: ImplicitScope} } case 301: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:1716 +//line sql.y:1718 { showTablesOpt := &ShowTablesOpt{Filter: yyDollar[4].showFilter} yyVAL.statement = &Show{Scope: VitessMetadataScope, Type: string(yyDollar[3].bytes), ShowTablesOpt: showTablesOpt} } case 302: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1721 +//line sql.y:1723 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 303: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1725 +//line sql.y:1727 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), Scope: ImplicitScope} } case 304: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1729 +//line sql.y:1731 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes) + " " + string(yyDollar[3].bytes), OnTable: yyDollar[5].tableName, Scope: ImplicitScope} } case 305: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1733 +//line sql.y:1735 { yyVAL.statement = &Show{Type: string(yyDollar[2].bytes), Scope: ImplicitScope} } case 306: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1738 +//line sql.y:1740 { // This should probably be a different type (ShowVitessTopoOpt), but // just getting the thing working for now @@ -5499,806 +5552,806 @@ yydefault: } case 307: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1752 +//line sql.y:1754 { yyVAL.statement = &Show{Type: string(yyDollar[2].colIdent.String()), Scope: ImplicitScope} } case 308: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1758 +//line sql.y:1760 { yyVAL.str = string(yyDollar[1].bytes) } case 309: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1762 +//line sql.y:1764 { yyVAL.str = string(yyDollar[1].bytes) } case 310: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1768 +//line sql.y:1770 { yyVAL.str = string(yyDollar[1].bytes) } case 311: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1772 +//line sql.y:1774 { yyVAL.str = string(yyDollar[1].bytes) } case 312: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1778 +//line sql.y:1780 { yyVAL.str = "" } case 313: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1782 +//line sql.y:1784 { yyVAL.str = "extended " } case 314: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1788 +//line sql.y:1790 { yyVAL.str = "" } case 315: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1792 +//line sql.y:1794 { yyVAL.str = "full " } case 316: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1798 +//line sql.y:1800 { yyVAL.str = string(yyDollar[1].bytes) } case 317: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1802 +//line sql.y:1804 { yyVAL.str = string(yyDollar[1].bytes) } case 318: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1808 +//line sql.y:1810 { yyVAL.str = "" } case 319: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1812 +//line sql.y:1814 { yyVAL.str = yyDollar[2].tableIdent.v } case 320: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1816 +//line sql.y:1818 { yyVAL.str = yyDollar[2].tableIdent.v } case 321: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1822 +//line sql.y:1824 { yyVAL.showFilter = nil } case 322: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1826 +//line sql.y:1828 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } case 323: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1830 +//line sql.y:1832 { yyVAL.showFilter = &ShowFilter{Filter: yyDollar[2].expr} } case 324: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1836 +//line sql.y:1838 { yyVAL.showFilter = nil } case 325: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1840 +//line sql.y:1842 { yyVAL.showFilter = &ShowFilter{Like: string(yyDollar[2].bytes)} } case 326: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1846 +//line sql.y:1848 { yyVAL.scope = ImplicitScope } case 327: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1850 +//line sql.y:1852 { yyVAL.scope = SessionScope } case 328: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1854 +//line sql.y:1856 { yyVAL.scope = GlobalScope } case 329: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1860 +//line sql.y:1862 { yyVAL.statement = &Use{DBName: yyDollar[2].tableIdent} } case 330: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1864 +//line sql.y:1866 { yyVAL.statement = &Use{DBName: TableIdent{v: ""}} } case 331: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1870 +//line sql.y:1872 { yyVAL.statement = &Begin{} } case 332: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1874 +//line sql.y:1876 { yyVAL.statement = &Begin{} } case 333: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1880 +//line sql.y:1882 { yyVAL.statement = &Commit{} } case 334: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1886 +//line sql.y:1888 { yyVAL.statement = &Rollback{} } case 335: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:1890 +//line sql.y:1892 { yyVAL.statement = &SRollback{Name: yyDollar[5].colIdent} } case 336: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1895 +//line sql.y:1897 { yyVAL.empty = struct{}{} } case 337: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1897 +//line sql.y:1899 { yyVAL.empty = struct{}{} } case 338: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1900 +//line sql.y:1902 { yyVAL.empty = struct{}{} } case 339: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1902 +//line sql.y:1904 { yyVAL.empty = struct{}{} } case 340: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1907 +//line sql.y:1909 { yyVAL.statement = &Savepoint{Name: yyDollar[2].colIdent} } case 341: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1913 +//line sql.y:1915 { yyVAL.statement = &Release{Name: yyDollar[3].colIdent} } case 342: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1918 +//line sql.y:1920 { yyVAL.explainType = EmptyType } case 343: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1922 +//line sql.y:1924 { yyVAL.explainType = JSONType } case 344: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1926 +//line sql.y:1928 { yyVAL.explainType = TreeType } case 345: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1930 +//line sql.y:1932 { yyVAL.explainType = VitessType } case 346: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1934 +//line sql.y:1936 { yyVAL.explainType = TraditionalType } case 347: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1938 +//line sql.y:1940 { yyVAL.explainType = AnalyzeType } case 348: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1944 +//line sql.y:1946 { yyVAL.bytes = yyDollar[1].bytes } case 349: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1948 +//line sql.y:1950 { yyVAL.bytes = yyDollar[1].bytes } case 350: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1952 +//line sql.y:1954 { yyVAL.bytes = yyDollar[1].bytes } case 351: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1958 +//line sql.y:1960 { yyVAL.statement = yyDollar[1].selStmt } case 352: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1962 +//line sql.y:1964 { yyVAL.statement = yyDollar[1].statement } case 353: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1966 +//line sql.y:1968 { yyVAL.statement = yyDollar[1].statement } case 354: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1970 +//line sql.y:1972 { yyVAL.statement = yyDollar[1].statement } case 355: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:1975 +//line sql.y:1977 { yyVAL.str = "" } case 356: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1979 +//line sql.y:1981 { yyVAL.str = "" } case 357: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:1983 +//line sql.y:1985 { yyVAL.str = "" } case 358: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1989 +//line sql.y:1991 { yyVAL.statement = &OtherRead{} } case 359: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:1993 +//line sql.y:1995 { yyVAL.statement = &Explain{Type: yyDollar[2].explainType, Statement: yyDollar[3].statement} } case 360: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:1999 +//line sql.y:2001 { yyVAL.statement = &OtherAdmin{} } case 361: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2003 +//line sql.y:2005 { yyVAL.statement = &OtherAdmin{} } case 362: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2007 +//line sql.y:2009 { yyVAL.statement = &OtherAdmin{} } case 363: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2011 +//line sql.y:2013 { yyVAL.statement = &OtherAdmin{} } case 364: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2017 +//line sql.y:2019 { yyVAL.statement = &DDL{Action: FlushDDLAction} } case 365: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2021 +//line sql.y:2023 { setAllowComments(yylex, true) } case 366: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2025 +//line sql.y:2027 { yyVAL.bytes2 = yyDollar[2].bytes2 setAllowComments(yylex, false) } case 367: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2031 +//line sql.y:2033 { yyVAL.bytes2 = nil } case 368: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2035 +//line sql.y:2037 { yyVAL.bytes2 = append(yyDollar[1].bytes2, yyDollar[2].bytes) } case 369: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2041 +//line sql.y:2043 { yyVAL.unionType = UnionBasic } case 370: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2045 +//line sql.y:2047 { yyVAL.unionType = UnionAll } case 371: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2049 +//line sql.y:2051 { yyVAL.unionType = UnionDistinct } case 372: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2054 +//line sql.y:2056 { yyVAL.str = "" } case 373: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2058 +//line sql.y:2060 { yyVAL.str = SQLNoCacheStr } case 374: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2062 +//line sql.y:2064 { yyVAL.str = SQLCacheStr } case 375: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2067 +//line sql.y:2069 { yyVAL.boolean = false } case 376: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2071 +//line sql.y:2073 { yyVAL.boolean = true } case 377: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2075 +//line sql.y:2077 { yyVAL.boolean = true } case 378: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2080 +//line sql.y:2082 { yyVAL.selectExprs = nil } case 379: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2084 +//line sql.y:2086 { yyVAL.selectExprs = yyDollar[1].selectExprs } case 380: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2089 +//line sql.y:2091 { yyVAL.strs = nil } case 381: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2093 +//line sql.y:2095 { yyVAL.strs = []string{yyDollar[1].str} } case 382: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2097 +//line sql.y:2099 { // TODO: This is a hack since I couldn't get it to work in a nicer way. I got 'conflicts: 8 shift/reduce' yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str} } case 383: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2101 +//line sql.y:2103 { yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str, yyDollar[3].str} } case 384: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2105 +//line sql.y:2107 { yyVAL.strs = []string{yyDollar[1].str, yyDollar[2].str, yyDollar[3].str, yyDollar[4].str} } case 385: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2111 +//line sql.y:2113 { yyVAL.str = SQLNoCacheStr } case 386: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2115 +//line sql.y:2117 { yyVAL.str = SQLCacheStr } case 387: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2119 +//line sql.y:2121 { yyVAL.str = DistinctStr } case 388: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2123 +//line sql.y:2125 { yyVAL.str = DistinctStr } case 389: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2127 +//line sql.y:2129 { yyVAL.str = StraightJoinHint } case 390: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2131 +//line sql.y:2133 { yyVAL.str = SQLCalcFoundRowsStr } case 391: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2137 +//line sql.y:2139 { yyVAL.selectExprs = SelectExprs{yyDollar[1].selectExpr} } case 392: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2141 +//line sql.y:2143 { yyVAL.selectExprs = append(yyVAL.selectExprs, yyDollar[3].selectExpr) } case 393: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2147 +//line sql.y:2149 { yyVAL.selectExpr = &StarExpr{} } case 394: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2151 +//line sql.y:2153 { yyVAL.selectExpr = &AliasedExpr{Expr: yyDollar[1].expr, As: yyDollar[2].colIdent} } case 395: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2155 +//line sql.y:2157 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Name: yyDollar[1].tableIdent}} } case 396: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2159 +//line sql.y:2161 { yyVAL.selectExpr = &StarExpr{TableName: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}} } case 397: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2164 +//line sql.y:2166 { yyVAL.colIdent = ColIdent{} } case 398: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2168 +//line sql.y:2170 { yyVAL.colIdent = yyDollar[1].colIdent } case 399: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2172 +//line sql.y:2174 { yyVAL.colIdent = yyDollar[2].colIdent } case 401: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2179 +//line sql.y:2181 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } case 402: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2184 +//line sql.y:2186 { yyVAL.tableExprs = TableExprs{&AliasedTableExpr{Expr: TableName{Name: NewTableIdent("dual")}}} } case 403: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2188 +//line sql.y:2190 { yyVAL.tableExprs = yyDollar[2].tableExprs } case 404: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2194 +//line sql.y:2196 { yyVAL.tableExprs = TableExprs{yyDollar[1].tableExpr} } case 405: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2198 +//line sql.y:2200 { yyVAL.tableExprs = append(yyVAL.tableExprs, yyDollar[3].tableExpr) } case 408: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2208 +//line sql.y:2210 { yyVAL.tableExpr = yyDollar[1].aliasedTableName } case 409: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2212 +//line sql.y:2214 { yyVAL.tableExpr = &AliasedTableExpr{Expr: yyDollar[1].subquery, As: yyDollar[3].tableIdent} } case 410: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2216 +//line sql.y:2218 { yyVAL.tableExpr = &ParenTableExpr{Exprs: yyDollar[2].tableExprs} } case 411: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2222 +//line sql.y:2224 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } case 412: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2228 +//line sql.y:2230 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, As: yyDollar[2].tableIdent, Hints: yyDollar[3].indexHints} } case 413: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2232 +//line sql.y:2234 { yyVAL.aliasedTableName = &AliasedTableExpr{Expr: yyDollar[1].tableName, Partitions: yyDollar[4].partitions, As: yyDollar[6].tableIdent, Hints: yyDollar[7].indexHints} } case 414: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2238 +//line sql.y:2240 { yyVAL.columns = Columns{yyDollar[1].colIdent} } case 415: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2242 +//line sql.y:2244 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } case 416: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2248 +//line sql.y:2250 { yyVAL.partitions = Partitions{yyDollar[1].colIdent} } case 417: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2252 +//line sql.y:2254 { yyVAL.partitions = append(yyVAL.partitions, yyDollar[3].colIdent) } case 418: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2265 +//line sql.y:2267 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 419: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2269 +//line sql.y:2271 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 420: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2273 +//line sql.y:2275 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr, Condition: yyDollar[4].joinCondition} } case 421: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2277 +//line sql.y:2279 { yyVAL.tableExpr = &JoinTableExpr{LeftExpr: yyDollar[1].tableExpr, Join: yyDollar[2].joinType, RightExpr: yyDollar[3].tableExpr} } case 422: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2283 +//line sql.y:2285 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } case 423: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2285 +//line sql.y:2287 { yyVAL.joinCondition = JoinCondition{Using: yyDollar[3].columns} } case 424: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2289 +//line sql.y:2291 { yyVAL.joinCondition = JoinCondition{} } case 425: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2291 +//line sql.y:2293 { yyVAL.joinCondition = yyDollar[1].joinCondition } case 426: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2295 +//line sql.y:2297 { yyVAL.joinCondition = JoinCondition{} } case 427: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2297 +//line sql.y:2299 { yyVAL.joinCondition = JoinCondition{On: yyDollar[2].expr} } case 428: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2300 +//line sql.y:2302 { yyVAL.empty = struct{}{} } case 429: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2302 +//line sql.y:2304 { yyVAL.empty = struct{}{} } case 430: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2305 +//line sql.y:2307 { yyVAL.tableIdent = NewTableIdent("") } case 431: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2309 +//line sql.y:2311 { yyVAL.tableIdent = yyDollar[1].tableIdent } case 432: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2313 +//line sql.y:2315 { yyVAL.tableIdent = yyDollar[2].tableIdent } case 434: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2320 +//line sql.y:2322 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } case 435: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2326 +//line sql.y:2328 { yyVAL.joinType = NormalJoinType } case 436: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2330 +//line sql.y:2332 { yyVAL.joinType = NormalJoinType } case 437: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2334 +//line sql.y:2336 { yyVAL.joinType = NormalJoinType } case 438: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2340 +//line sql.y:2342 { yyVAL.joinType = StraightJoinType } case 439: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2346 +//line sql.y:2348 { yyVAL.joinType = LeftJoinType } case 440: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2350 +//line sql.y:2352 { yyVAL.joinType = LeftJoinType } case 441: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2354 +//line sql.y:2356 { yyVAL.joinType = RightJoinType } case 442: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2358 +//line sql.y:2360 { yyVAL.joinType = RightJoinType } case 443: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2364 +//line sql.y:2366 { yyVAL.joinType = NaturalJoinType } case 444: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2368 +//line sql.y:2370 { if yyDollar[2].joinType == LeftJoinType { yyVAL.joinType = NaturalLeftJoinType @@ -6308,487 +6361,487 @@ yydefault: } case 445: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2378 +//line sql.y:2380 { yyVAL.tableName = yyDollar[2].tableName } case 446: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2382 +//line sql.y:2384 { yyVAL.tableName = yyDollar[1].tableName } case 447: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2388 +//line sql.y:2390 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } case 448: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2392 +//line sql.y:2394 { yyVAL.tableName = TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent} } case 449: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2398 +//line sql.y:2400 { yyVAL.tableName = TableName{Name: yyDollar[1].tableIdent} } case 450: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2403 +//line sql.y:2405 { yyVAL.indexHints = nil } case 451: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2407 +//line sql.y:2409 { yyVAL.indexHints = &IndexHints{Type: UseOp, Indexes: yyDollar[4].columns} } case 452: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2411 +//line sql.y:2413 { yyVAL.indexHints = &IndexHints{Type: UseOp} } case 453: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2415 +//line sql.y:2417 { yyVAL.indexHints = &IndexHints{Type: IgnoreOp, Indexes: yyDollar[4].columns} } case 454: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2419 +//line sql.y:2421 { yyVAL.indexHints = &IndexHints{Type: ForceOp, Indexes: yyDollar[4].columns} } case 455: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2424 +//line sql.y:2426 { yyVAL.expr = nil } case 456: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2428 +//line sql.y:2430 { yyVAL.expr = yyDollar[2].expr } case 457: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2434 +//line sql.y:2436 { yyVAL.expr = yyDollar[1].expr } case 458: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2438 +//line sql.y:2440 { yyVAL.expr = &AndExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } case 459: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2442 +//line sql.y:2444 { yyVAL.expr = &OrExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } case 460: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2446 +//line sql.y:2448 { yyVAL.expr = &XorExpr{Left: yyDollar[1].expr, Right: yyDollar[3].expr} } case 461: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2450 +//line sql.y:2452 { yyVAL.expr = &NotExpr{Expr: yyDollar[2].expr} } case 462: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2454 +//line sql.y:2456 { yyVAL.expr = &IsExpr{Operator: yyDollar[3].isExprOperator, Expr: yyDollar[1].expr} } case 463: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2458 +//line sql.y:2460 { yyVAL.expr = yyDollar[1].expr } case 464: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2462 +//line sql.y:2464 { yyVAL.expr = &Default{ColName: yyDollar[2].str} } case 465: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2468 +//line sql.y:2470 { yyVAL.str = "" } case 466: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2472 +//line sql.y:2474 { yyVAL.str = string(yyDollar[2].colIdent.String()) } case 467: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2478 +//line sql.y:2480 { yyVAL.boolVal = BoolVal(true) } case 468: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2482 +//line sql.y:2484 { yyVAL.boolVal = BoolVal(false) } case 469: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2488 +//line sql.y:2490 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: yyDollar[2].comparisonExprOperator, Right: yyDollar[3].expr} } case 470: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2492 +//line sql.y:2494 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: InOp, Right: yyDollar[3].colTuple} } case 471: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2496 +//line sql.y:2498 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotInOp, Right: yyDollar[4].colTuple} } case 472: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2500 +//line sql.y:2502 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: LikeOp, Right: yyDollar[3].expr, Escape: yyDollar[4].expr} } case 473: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2504 +//line sql.y:2506 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotLikeOp, Right: yyDollar[4].expr, Escape: yyDollar[5].expr} } case 474: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2508 +//line sql.y:2510 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: RegexpOp, Right: yyDollar[3].expr} } case 475: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2512 +//line sql.y:2514 { yyVAL.expr = &ComparisonExpr{Left: yyDollar[1].expr, Operator: NotRegexpOp, Right: yyDollar[4].expr} } case 476: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2516 +//line sql.y:2518 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: BetweenOp, From: yyDollar[3].expr, To: yyDollar[5].expr} } case 477: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2520 +//line sql.y:2522 { yyVAL.expr = &RangeCond{Left: yyDollar[1].expr, Operator: NotBetweenOp, From: yyDollar[4].expr, To: yyDollar[6].expr} } case 478: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2524 +//line sql.y:2526 { yyVAL.expr = &ExistsExpr{Subquery: yyDollar[2].subquery} } case 479: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2530 +//line sql.y:2532 { yyVAL.isExprOperator = IsNullOp } case 480: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2534 +//line sql.y:2536 { yyVAL.isExprOperator = IsNotNullOp } case 481: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2538 +//line sql.y:2540 { yyVAL.isExprOperator = IsTrueOp } case 482: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2542 +//line sql.y:2544 { yyVAL.isExprOperator = IsNotTrueOp } case 483: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2546 +//line sql.y:2548 { yyVAL.isExprOperator = IsFalseOp } case 484: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2550 +//line sql.y:2552 { yyVAL.isExprOperator = IsNotFalseOp } case 485: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2556 +//line sql.y:2558 { yyVAL.comparisonExprOperator = EqualOp } case 486: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2560 +//line sql.y:2562 { yyVAL.comparisonExprOperator = LessThanOp } case 487: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2564 +//line sql.y:2566 { yyVAL.comparisonExprOperator = GreaterThanOp } case 488: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2568 +//line sql.y:2570 { yyVAL.comparisonExprOperator = LessEqualOp } case 489: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2572 +//line sql.y:2574 { yyVAL.comparisonExprOperator = GreaterEqualOp } case 490: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2576 +//line sql.y:2578 { yyVAL.comparisonExprOperator = NotEqualOp } case 491: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2580 +//line sql.y:2582 { yyVAL.comparisonExprOperator = NullSafeEqualOp } case 492: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2585 +//line sql.y:2587 { yyVAL.expr = nil } case 493: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2589 +//line sql.y:2591 { yyVAL.expr = yyDollar[2].expr } case 494: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2595 +//line sql.y:2597 { yyVAL.colTuple = yyDollar[1].valTuple } case 495: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2599 +//line sql.y:2601 { yyVAL.colTuple = yyDollar[1].subquery } case 496: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2603 +//line sql.y:2605 { yyVAL.colTuple = ListArg(yyDollar[1].bytes) } case 497: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2609 +//line sql.y:2611 { yyVAL.subquery = &Subquery{yyDollar[2].selStmt} } case 498: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2615 +//line sql.y:2617 { yyVAL.exprs = Exprs{yyDollar[1].expr} } case 499: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2619 +//line sql.y:2621 { yyVAL.exprs = append(yyDollar[1].exprs, yyDollar[3].expr) } case 500: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2625 +//line sql.y:2627 { yyVAL.expr = yyDollar[1].expr } case 501: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2629 +//line sql.y:2631 { yyVAL.expr = yyDollar[1].boolVal } case 502: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2633 +//line sql.y:2635 { yyVAL.expr = yyDollar[1].colName } case 503: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2637 +//line sql.y:2639 { yyVAL.expr = yyDollar[1].expr } case 504: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2641 +//line sql.y:2643 { yyVAL.expr = yyDollar[1].subquery } case 505: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2645 +//line sql.y:2647 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitAndOp, Right: yyDollar[3].expr} } case 506: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2649 +//line sql.y:2651 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitOrOp, Right: yyDollar[3].expr} } case 507: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2653 +//line sql.y:2655 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: BitXorOp, Right: yyDollar[3].expr} } case 508: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2657 +//line sql.y:2659 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: PlusOp, Right: yyDollar[3].expr} } case 509: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2661 +//line sql.y:2663 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MinusOp, Right: yyDollar[3].expr} } case 510: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2665 +//line sql.y:2667 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: MultOp, Right: yyDollar[3].expr} } case 511: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2669 +//line sql.y:2671 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: DivOp, Right: yyDollar[3].expr} } case 512: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2673 +//line sql.y:2675 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: IntDivOp, Right: yyDollar[3].expr} } case 513: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2677 +//line sql.y:2679 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModOp, Right: yyDollar[3].expr} } case 514: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2681 +//line sql.y:2683 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ModOp, Right: yyDollar[3].expr} } case 515: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2685 +//line sql.y:2687 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftLeftOp, Right: yyDollar[3].expr} } case 516: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2689 +//line sql.y:2691 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].expr, Operator: ShiftRightOp, Right: yyDollar[3].expr} } case 517: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2693 +//line sql.y:2695 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONExtractOp, Right: yyDollar[3].expr} } case 518: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2697 +//line sql.y:2699 { yyVAL.expr = &BinaryExpr{Left: yyDollar[1].colName, Operator: JSONUnquoteExtractOp, Right: yyDollar[3].expr} } case 519: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2701 +//line sql.y:2703 { yyVAL.expr = &CollateExpr{Expr: yyDollar[1].expr, Charset: yyDollar[3].str} } case 520: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2705 +//line sql.y:2707 { yyVAL.expr = &UnaryExpr{Operator: BinaryOp, Expr: yyDollar[2].expr} } case 521: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2709 +//line sql.y:2711 { yyVAL.expr = &UnaryExpr{Operator: UBinaryOp, Expr: yyDollar[2].expr} } case 522: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2713 +//line sql.y:2715 { yyVAL.expr = &UnaryExpr{Operator: Utf8Op, Expr: yyDollar[2].expr} } case 523: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2717 +//line sql.y:2719 { yyVAL.expr = &UnaryExpr{Operator: Utf8mb4Op, Expr: yyDollar[2].expr} } case 524: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2721 +//line sql.y:2723 { yyVAL.expr = &UnaryExpr{Operator: Latin1Op, Expr: yyDollar[2].expr} } case 525: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2725 +//line sql.y:2727 { if num, ok := yyDollar[2].expr.(*Literal); ok && num.Type == IntVal { yyVAL.expr = num @@ -6798,7 +6851,7 @@ yydefault: } case 526: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2733 +//line sql.y:2735 { if num, ok := yyDollar[2].expr.(*Literal); ok && num.Type == IntVal { // Handle double negative @@ -6814,19 +6867,19 @@ yydefault: } case 527: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2747 +//line sql.y:2749 { yyVAL.expr = &UnaryExpr{Operator: TildaOp, Expr: yyDollar[2].expr} } case 528: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2751 +//line sql.y:2753 { yyVAL.expr = &UnaryExpr{Operator: BangOp, Expr: yyDollar[2].expr} } case 529: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2755 +//line sql.y:2757 { // This rule prevents the usage of INTERVAL // as a function. If support is needed for that, @@ -6836,325 +6889,325 @@ yydefault: } case 534: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2773 +//line sql.y:2775 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Exprs: yyDollar[3].selectExprs} } case 535: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2777 +//line sql.y:2779 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } case 536: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2781 +//line sql.y:2783 { yyVAL.expr = &FuncExpr{Name: yyDollar[1].colIdent, Distinct: true, Exprs: yyDollar[4].selectExprs} } case 537: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2785 +//line sql.y:2787 { yyVAL.expr = &FuncExpr{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].colIdent, Exprs: yyDollar[5].selectExprs} } case 538: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2795 +//line sql.y:2797 { yyVAL.expr = &FuncExpr{Name: NewColIdent("left"), Exprs: yyDollar[3].selectExprs} } case 539: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2799 +//line sql.y:2801 { yyVAL.expr = &FuncExpr{Name: NewColIdent("right"), Exprs: yyDollar[3].selectExprs} } case 540: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2803 +//line sql.y:2805 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } case 541: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2807 +//line sql.y:2809 { yyVAL.expr = &ConvertExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].convertType} } case 542: yyDollar = yyS[yypt-6 : yypt+1] -//line sql.y:2811 +//line sql.y:2813 { yyVAL.expr = &ConvertUsingExpr{Expr: yyDollar[3].expr, Type: yyDollar[5].str} } case 543: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2815 +//line sql.y:2817 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 544: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2819 +//line sql.y:2821 { yyVAL.expr = &SubstrExpr{Name: yyDollar[3].colName, From: yyDollar[5].expr, To: yyDollar[7].expr} } case 545: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2823 +//line sql.y:2825 { yyVAL.expr = &SubstrExpr{StrVal: NewStrLiteral(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } case 546: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2827 +//line sql.y:2829 { yyVAL.expr = &SubstrExpr{StrVal: NewStrLiteral(yyDollar[3].bytes), From: yyDollar[5].expr, To: yyDollar[7].expr} } case 547: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:2831 +//line sql.y:2833 { yyVAL.expr = &MatchExpr{Columns: yyDollar[3].selectExprs, Expr: yyDollar[7].expr, Option: yyDollar[8].matchExprOption} } case 548: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2835 +//line sql.y:2837 { yyVAL.expr = &GroupConcatExpr{Distinct: yyDollar[3].boolean, Exprs: yyDollar[4].selectExprs, OrderBy: yyDollar[5].orderBy, Separator: yyDollar[6].str, Limit: yyDollar[7].limit} } case 549: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:2839 +//line sql.y:2841 { yyVAL.expr = &CaseExpr{Expr: yyDollar[2].expr, Whens: yyDollar[3].whens, Else: yyDollar[4].expr} } case 550: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2843 +//line sql.y:2845 { yyVAL.expr = &ValuesFuncExpr{Name: yyDollar[3].colName} } case 551: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2853 +//line sql.y:2855 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } case 552: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2857 +//line sql.y:2859 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } case 553: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2861 +//line sql.y:2863 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } case 554: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2866 +//line sql.y:2868 { yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } case 555: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2871 +//line sql.y:2873 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } case 556: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2876 +//line sql.y:2878 { yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } case 557: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2882 +//line sql.y:2884 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } case 558: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2887 +//line sql.y:2889 { yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } case 559: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2892 +//line sql.y:2894 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} } case 560: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2896 +//line sql.y:2898 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} } case 561: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2900 +//line sql.y:2902 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} } case 562: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2905 +//line sql.y:2907 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} } case 563: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2910 +//line sql.y:2912 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} } case 564: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:2915 +//line sql.y:2917 { yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} } case 565: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2919 +//line sql.y:2921 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } case 566: yyDollar = yyS[yypt-8 : yypt+1] -//line sql.y:2923 +//line sql.y:2925 { yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } case 569: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2933 +//line sql.y:2935 { yyVAL.expr = yyDollar[2].expr } case 570: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2943 +//line sql.y:2945 { yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } case 571: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2947 +//line sql.y:2949 { yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } case 572: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2951 +//line sql.y:2953 { yyVAL.expr = &FuncExpr{Name: NewColIdent("schema"), Exprs: yyDollar[3].selectExprs} } case 573: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2955 +//line sql.y:2957 { yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } case 574: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2959 +//line sql.y:2961 { yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } case 575: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2963 +//line sql.y:2965 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 576: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2967 +//line sql.y:2969 { yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 577: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:2973 +//line sql.y:2975 { yyVAL.matchExprOption = NoOption } case 578: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2977 +//line sql.y:2979 { yyVAL.matchExprOption = BooleanModeOpt } case 579: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:2981 +//line sql.y:2983 { yyVAL.matchExprOption = NaturalLanguageModeOpt } case 580: yyDollar = yyS[yypt-7 : yypt+1] -//line sql.y:2985 +//line sql.y:2987 { yyVAL.matchExprOption = NaturalLanguageModeWithQueryExpansionOpt } case 581: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:2989 +//line sql.y:2991 { yyVAL.matchExprOption = QueryExpansionOpt } case 582: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2995 +//line sql.y:2997 { yyVAL.str = string(yyDollar[1].colIdent.String()) } case 583: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:2999 +//line sql.y:3001 { yyVAL.str = string(yyDollar[1].bytes) } case 584: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3005 +//line sql.y:3007 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 585: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3009 +//line sql.y:3011 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Operator: CharacterSetOp} } case 586: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3013 +//line sql.y:3015 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: string(yyDollar[3].colIdent.String())} } case 587: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3017 +//line sql.y:3019 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 588: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3021 +//line sql.y:3023 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 589: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3025 +//line sql.y:3027 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length @@ -7162,169 +7215,169 @@ yydefault: } case 590: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3031 +//line sql.y:3033 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 591: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3035 +//line sql.y:3037 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 592: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3039 +//line sql.y:3041 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 593: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3043 +//line sql.y:3045 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 594: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3047 +//line sql.y:3049 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 595: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3051 +//line sql.y:3053 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 596: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3055 +//line sql.y:3057 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 597: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3060 +//line sql.y:3062 { yyVAL.expr = nil } case 598: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3064 +//line sql.y:3066 { yyVAL.expr = yyDollar[1].expr } case 599: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3069 +//line sql.y:3071 { yyVAL.str = string("") } case 600: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3073 +//line sql.y:3075 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } case 601: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3079 +//line sql.y:3081 { yyVAL.whens = []*When{yyDollar[1].when} } case 602: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3083 +//line sql.y:3085 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } case 603: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3089 +//line sql.y:3091 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } case 604: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3094 +//line sql.y:3096 { yyVAL.expr = nil } case 605: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3098 +//line sql.y:3100 { yyVAL.expr = yyDollar[2].expr } case 606: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3104 +//line sql.y:3106 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } case 607: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3108 +//line sql.y:3110 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } case 608: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3112 +//line sql.y:3114 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } case 609: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3118 +//line sql.y:3120 { yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } case 610: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3122 +//line sql.y:3124 { yyVAL.expr = NewHexLiteral(yyDollar[1].bytes) } case 611: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3126 +//line sql.y:3128 { yyVAL.expr = NewBitLiteral(yyDollar[1].bytes) } case 612: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3130 +//line sql.y:3132 { yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } case 613: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3134 +//line sql.y:3136 { yyVAL.expr = NewFloatLiteral(yyDollar[1].bytes) } case 614: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3138 +//line sql.y:3140 { yyVAL.expr = NewHexNumLiteral(yyDollar[1].bytes) } case 615: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3142 +//line sql.y:3144 { yyVAL.expr = NewArgument(yyDollar[1].bytes) } case 616: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3146 +//line sql.y:3148 { yyVAL.expr = &NullVal{} } case 617: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3152 +//line sql.y:3154 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -7335,223 +7388,223 @@ yydefault: } case 618: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3161 +//line sql.y:3163 { yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } case 619: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3165 +//line sql.y:3167 { yyVAL.expr = NewArgument(yyDollar[1].bytes) } case 620: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3170 +//line sql.y:3172 { yyVAL.exprs = nil } case 621: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3174 +//line sql.y:3176 { yyVAL.exprs = yyDollar[3].exprs } case 622: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3179 +//line sql.y:3181 { yyVAL.expr = nil } case 623: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3183 +//line sql.y:3185 { yyVAL.expr = yyDollar[2].expr } case 624: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3188 +//line sql.y:3190 { yyVAL.orderBy = nil } case 625: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3192 +//line sql.y:3194 { yyVAL.orderBy = yyDollar[3].orderBy } case 626: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3198 +//line sql.y:3200 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } case 627: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3202 +//line sql.y:3204 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } case 628: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3208 +//line sql.y:3210 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].orderDirection} } case 629: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3213 +//line sql.y:3215 { yyVAL.orderDirection = AscOrder } case 630: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3217 +//line sql.y:3219 { yyVAL.orderDirection = AscOrder } case 631: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3221 +//line sql.y:3223 { yyVAL.orderDirection = DescOrder } case 632: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3226 +//line sql.y:3228 { yyVAL.limit = nil } case 633: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3230 +//line sql.y:3232 { yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } case 634: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3234 +//line sql.y:3236 { yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } case 635: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3238 +//line sql.y:3240 { yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } case 636: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3243 +//line sql.y:3245 { yyVAL.lock = NoLock } case 637: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3247 +//line sql.y:3249 { yyVAL.lock = ForUpdateLock } case 638: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3251 +//line sql.y:3253 { yyVAL.lock = ShareModeLock } case 639: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3264 +//line sql.y:3266 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } case 640: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3268 +//line sql.y:3270 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } case 641: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3272 +//line sql.y:3274 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } case 642: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3276 +//line sql.y:3278 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } case 643: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3282 +//line sql.y:3284 { yyVAL.columns = Columns{yyDollar[1].colIdent} } case 644: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3286 +//line sql.y:3288 { yyVAL.columns = Columns{yyDollar[3].colIdent} } case 645: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3290 +//line sql.y:3292 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } case 646: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3294 +//line sql.y:3296 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } case 647: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3299 +//line sql.y:3301 { yyVAL.updateExprs = nil } case 648: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3303 +//line sql.y:3305 { yyVAL.updateExprs = yyDollar[5].updateExprs } case 649: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3309 +//line sql.y:3311 { yyVAL.values = Values{yyDollar[1].valTuple} } case 650: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3313 +//line sql.y:3315 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } case 651: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3319 +//line sql.y:3321 { yyVAL.valTuple = yyDollar[1].valTuple } case 652: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3323 +//line sql.y:3325 { yyVAL.valTuple = ValTuple{} } case 653: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3329 +//line sql.y:3331 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } case 654: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3335 +//line sql.y:3337 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = yyDollar[1].valTuple[0] @@ -7561,317 +7614,340 @@ yydefault: } case 655: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3345 +//line sql.y:3347 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } case 656: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3349 +//line sql.y:3351 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } case 657: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3355 +//line sql.y:3357 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } case 658: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3361 +//line sql.y:3363 { yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } case 659: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3365 +//line sql.y:3367 { yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } case 660: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3371 +//line sql.y:3373 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("on"))} } case 661: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3375 +//line sql.y:3377 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("off"))} } case 662: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3379 +//line sql.y:3381 { yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: yyDollar[3].expr} } case 663: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3383 +//line sql.y:3385 { yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Scope: ImplicitScope, Expr: yyDollar[2].expr} } case 664: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3387 +//line sql.y:3389 { yyDollar[2].setExpr.Scope = yyDollar[1].scope yyVAL.setExpr = yyDollar[2].setExpr } case 666: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3395 +//line sql.y:3397 { yyVAL.bytes = []byte("charset") } case 668: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3402 +//line sql.y:3404 { yyVAL.expr = NewStrLiteral([]byte(yyDollar[1].colIdent.String())) } case 669: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3406 +//line sql.y:3408 { yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } case 670: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3410 +//line sql.y:3412 { yyVAL.expr = &Default{} } case 673: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3419 +//line sql.y:3421 { yyVAL.boolean = false } case 674: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3421 +//line sql.y:3423 { yyVAL.boolean = true } case 675: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3424 +//line sql.y:3426 { yyVAL.boolean = false } case 676: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3426 +//line sql.y:3428 { yyVAL.boolean = true } case 677: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3429 +//line sql.y:3431 { yyVAL.ignore = false } case 678: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3431 +//line sql.y:3433 { yyVAL.ignore = true } case 679: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3435 +//line sql.y:3437 { yyVAL.empty = struct{}{} } case 680: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3437 +//line sql.y:3439 { yyVAL.empty = struct{}{} } case 681: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3439 +//line sql.y:3441 { yyVAL.empty = struct{}{} } case 682: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3441 +//line sql.y:3443 { yyVAL.empty = struct{}{} } case 683: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3443 +//line sql.y:3445 { yyVAL.empty = struct{}{} } case 684: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3445 +//line sql.y:3447 { yyVAL.empty = struct{}{} } case 685: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3447 +//line sql.y:3449 { yyVAL.empty = struct{}{} } case 686: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3449 +//line sql.y:3451 { yyVAL.empty = struct{}{} } case 687: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3451 +//line sql.y:3453 { yyVAL.empty = struct{}{} } case 688: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3453 +//line sql.y:3455 { yyVAL.empty = struct{}{} } case 689: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3456 +//line sql.y:3459 { - yyVAL.empty = struct{}{} + yyVAL.OnlineDDLHint = &OnlineDDLHint{} } case 690: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3458 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3463 { - yyVAL.empty = struct{}{} + yyVAL.OnlineDDLHint = &OnlineDDLHint{ + Strategy: DDLStrategy(yyDollar[2].bytes), + } } case 691: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3460 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3469 { - yyVAL.empty = struct{}{} + yyVAL.OnlineDDLHint = &OnlineDDLHint{ + Strategy: DDLStrategy(yyDollar[2].bytes), + Options: string(yyDollar[3].bytes), + } } case 692: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3464 + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:3477 { yyVAL.empty = struct{}{} } case 693: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3466 +//line sql.y:3479 { yyVAL.empty = struct{}{} } case 694: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3469 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3481 { yyVAL.empty = struct{}{} } case 695: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3471 +//line sql.y:3485 { yyVAL.empty = struct{}{} } case 696: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3473 +//line sql.y:3487 { yyVAL.empty = struct{}{} } case 697: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3476 +//line sql.y:3490 { - yyVAL.colIdent = ColIdent{} + yyVAL.empty = struct{}{} } case 698: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3492 + { + yyVAL.empty = struct{}{} + } + case 699: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3494 + { + yyVAL.empty = struct{}{} + } + case 700: + yyDollar = yyS[yypt-0 : yypt+1] +//line sql.y:3497 + { + yyVAL.colIdent = ColIdent{} + } + case 701: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3478 +//line sql.y:3499 { yyVAL.colIdent = yyDollar[2].colIdent } - case 699: + case 702: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3482 +//line sql.y:3503 { yyVAL.colIdent = yyDollar[1].colIdent } - case 700: + case 703: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3486 +//line sql.y:3507 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 702: + case 705: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3493 +//line sql.y:3514 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 703: + case 706: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3499 +//line sql.y:3520 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].colIdent.String())) } - case 704: + case 707: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3503 +//line sql.y:3524 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 706: + case 709: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3510 +//line sql.y:3531 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 1005: + case 1008: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3834 +//line sql.y:3855 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 1006: + case 1009: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3843 +//line sql.y:3864 { decNesting(yylex) } - case 1007: + case 1010: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3848 +//line sql.y:3869 { skipToEnd(yylex) } - case 1008: + case 1011: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3853 +//line sql.y:3874 { skipToEnd(yylex) } - case 1009: + case 1012: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3857 +//line sql.y:3878 { skipToEnd(yylex) } - case 1010: + case 1013: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3861 +//line sql.y:3882 { skipToEnd(yylex) } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index e142dbf905f..d1bcf77a820 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -101,6 +101,7 @@ func skipToEnd(yylex interface{}) { colKeyOpt ColumnKeyOption optVal Expr LengthScaleOption LengthScaleOption + OnlineDDLHint *OnlineDDLHint columnDefinition *ColumnDefinition indexDefinition *IndexDefinition indexInfo *IndexInfo @@ -301,6 +302,7 @@ func skipToEnd(yylex interface{}) { %type for_from %type default_opt %type ignore_opt +%type online_hint_opt %type full_opt from_database_opt tables_or_processlist columns_or_fields extended_opt %type like_or_where_opt like_opt %type exists_opt not_exists_opt null_opt @@ -1399,35 +1401,35 @@ table_opt_value: } alter_statement: - ALTER ignore_opt TABLE table_name non_add_drop_or_rename_operation skip_to_end + ALTER online_hint_opt TABLE table_name non_add_drop_or_rename_operation skip_to_end { - $$ = &DDL{Action: AlterDDLAction, Table: $4} + $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} } -| ALTER ignore_opt TABLE table_name ADD alter_object_type skip_to_end +| ALTER online_hint_opt TABLE table_name ADD alter_object_type skip_to_end { - $$ = &DDL{Action: AlterDDLAction, Table: $4} + $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} } -| ALTER ignore_opt TABLE table_name DROP alter_object_type skip_to_end +| ALTER online_hint_opt TABLE table_name DROP alter_object_type skip_to_end { - $$ = &DDL{Action: AlterDDLAction, Table: $4} + $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} } -| ALTER ignore_opt TABLE table_name RENAME to_opt table_name +| ALTER online_hint_opt TABLE table_name RENAME to_opt table_name { // Change this to a rename statement $$ = &DDL{Action: RenameDDLAction, FromTables: TableNames{$4}, ToTables: TableNames{$7}} } -| ALTER ignore_opt TABLE table_name RENAME index_opt skip_to_end +| ALTER online_hint_opt TABLE table_name RENAME index_opt skip_to_end { // Rename an index can just be an alter - $$ = &DDL{Action: AlterDDLAction, Table: $4} + $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4} } | ALTER VIEW table_name ddl_skip_to_end { $$ = &DDL{Action: AlterDDLAction, Table: $3.ToViewName()} } -| ALTER ignore_opt TABLE table_name partition_operation +| ALTER online_hint_opt TABLE table_name partition_operation { - $$ = &DDL{Action: AlterDDLAction, Table: $4, PartitionSpec: $5} + $$ = &DDL{Action: AlterDDLAction, OnlineHint: $2, Table: $4, PartitionSpec: $5} } | ALTER DATABASE id_or_var ddl_skip_to_end { @@ -3452,6 +3454,25 @@ non_add_drop_or_rename_operation: | id_or_var { $$ = struct{}{} } + +online_hint_opt: + { + $$ = &OnlineDDLHint{} + } +| WITH STRING + { + $$ = &OnlineDDLHint{ + Strategy: DDLStrategy($2), + } + } +| WITH STRING STRING + { + $$ = &OnlineDDLHint{ + Strategy: DDLStrategy($2), + Options: string($3), + } + } + to_opt: { $$ = struct{}{} } | TO diff --git a/go/vt/sqlparser/utils.go b/go/vt/sqlparser/utils.go new file mode 100644 index 00000000000..1de7833a58e --- /dev/null +++ b/go/vt/sqlparser/utils.go @@ -0,0 +1,112 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlparser + +import ( + "fmt" + "sort" + + querypb "vitess.io/vitess/go/vt/proto/query" +) + +// QueryMatchesTemplates sees if the given query has the same fingerprint as one of the given templates +// (one is enough) +func QueryMatchesTemplates(query string, queryTemplates []string) (match bool, err error) { + if len(queryTemplates) == 0 { + return false, fmt.Errorf("No templates found") + } + bv := make(map[string]*querypb.BindVariable) + + normalize := func(q string) (string, error) { + q, err := NormalizeAlphabetically(q) + if err != nil { + return "", err + } + stmt, err := Parse(q) + if err != nil { + return "", err + } + Normalize(stmt, bv, "") + normalized := String(stmt) + return normalized, nil + } + + normalizedQuery, err := normalize(query) + if err != nil { + return false, err + } + + for _, template := range queryTemplates { + normalizedTemplate, err := normalize(template) + if err != nil { + return false, err + } + + // compare! + if normalizedTemplate == normalizedQuery { + return true, nil + } + } + return false, nil +} + +// NormalizeAlphabetically rewrites given query such that: +// - WHERE 'AND' expressions are reordered alphabetically +func NormalizeAlphabetically(query string) (normalized string, err error) { + stmt, err := Parse(query) + if err != nil { + return normalized, err + } + var where *Where + switch stmt := stmt.(type) { + case *Update: + where = stmt.Where + case *Delete: + where = stmt.Where + case *Select: + where = stmt.Where + } + if where != nil { + andExprs := SplitAndExpression(nil, where.Expr) + sort.SliceStable(andExprs, func(i, j int) bool { + return String(andExprs[i]) < String(andExprs[j]) + }) + var newWhere *Where + for _, expr := range andExprs { + if newWhere == nil { + newWhere = &Where{ + Type: WhereClause, + Expr: expr, + } + } else { + newWhere.Expr = &AndExpr{ + Left: newWhere.Expr, + Right: expr, + } + } + } + switch stmt := stmt.(type) { + case *Update: + stmt.Where = newWhere + case *Delete: + stmt.Where = newWhere + case *Select: + stmt.Where = newWhere + } + } + return String(stmt), nil +} diff --git a/go/vt/sqlparser/utils_test.go b/go/vt/sqlparser/utils_test.go new file mode 100644 index 00000000000..a073f5127cc --- /dev/null +++ b/go/vt/sqlparser/utils_test.go @@ -0,0 +1,146 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package sqlparser + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNormalizeAlphabetically(t *testing.T) { + testcases := []struct { + in string + out string + }{{ + in: "select * from tbl", + out: "select * from tbl", + }, { + in: "select * from tbl where a=3", + out: "select * from tbl where a = 3", + }, { + in: "select * from tbl where a=3 and b=4", + out: "select * from tbl where a = 3 and b = 4", + }, { + in: "select * from tbl where b=4 and a=3", + out: "select * from tbl where a = 3 and b = 4", + }, { + in: "select * from tbl where b=4 and c>5 and a=3", + out: "select * from tbl where a = 3 and b = 4 and c > 5", + }, { + in: "select * from tbl where b=4 or a=3", + out: "select * from tbl where b = 4 or a = 3", + }} + + for _, tc := range testcases { + normalized, err := NormalizeAlphabetically(tc.in) + assert.NoError(t, err) + assert.Equal(t, tc.out, normalized) + } +} + +func TestQueryMatchesTemplates(t *testing.T) { + testcases := []struct { + q string + tmpl []string + out bool + }{{ + q: "select id from tbl", + tmpl: []string{ + "select id from tbl", + }, + out: true, + }, { + q: "select id from tbl", + tmpl: []string{ + "select name from tbl", + "select id from tbl", + }, + out: true, + }, { + q: "select id from tbl where a=3", + tmpl: []string{ + "select id from tbl", + }, + out: false, + }, { + // int value + q: "select id from tbl where a=3", + tmpl: []string{ + "select name from tbl where a=17", + "select id from tbl where a=5", + }, + out: true, + }, { + // string value + q: "select id from tbl where a='abc'", + tmpl: []string{ + "select name from tbl where a='x'", + "select id from tbl where a='y'", + }, + out: true, + }, { + // two params + q: "select id from tbl where a='abc' and b='def'", + tmpl: []string{ + "select name from tbl where a='x' and b = 'y'", + "select id from tbl where a='x' and b = 'y'", + }, + out: true, + }, { + // no match + q: "select id from tbl where a='abc' and b='def'", + tmpl: []string{ + "select name from tbl where a='x' and b = 'y'", + "select id from tbl where a='x' and c = 'y'", + }, + out: false, + }, { + // reorder AND params + q: "select id from tbl where a='abc' and b='def'", + tmpl: []string{ + "select id from tbl where b='x' and a = 'y'", + }, + out: true, + }, { + // no reorder OR params + q: "select id from tbl where a='abc' or b='def'", + tmpl: []string{ + "select id from tbl where b='x' or a = 'y'", + }, + out: false, + }, { + // strict reorder OR params + q: "select id from tbl where a='abc' or b='def'", + tmpl: []string{ + "select id from tbl where a='x' or b = 'y'", + }, + out: true, + }, { + // reorder AND params, range test + q: "select id from tbl where a >'abc' and b<3", + tmpl: []string{ + "select id from tbl where b<17 and a > 'y'", + }, + out: true, + }} + for _, tc := range testcases { + match, err := QueryMatchesTemplates(tc.q, tc.tmpl) + assert.NoError(t, err) + assert.Equal(t, tc.out, match) + } +} diff --git a/go/vt/vtcombo/tablet_map.go b/go/vt/vtcombo/tablet_map.go index af4a2e2ec02..406407cd045 100644 --- a/go/vt/vtcombo/tablet_map.go +++ b/go/vt/vtcombo/tablet_map.go @@ -699,6 +699,10 @@ func (itmc *internalTabletManagerClient) GetSlaves(ctx context.Context, tablet * return nil, fmt.Errorf("not implemented in vtcombo") } +func (itmc *internalTabletManagerClient) VExec(ctx context.Context, tablet *topodatapb.Tablet, query, workflow, keyspace string) (*querypb.QueryResult, error) { + return nil, fmt.Errorf("not implemented in vtcombo") +} + func (itmc *internalTabletManagerClient) VReplicationExec(ctx context.Context, tablet *topodatapb.Tablet, query string) (*querypb.QueryResult, error) { return nil, fmt.Errorf("not implemented in vtcombo") } diff --git a/go/vt/vtctl/query.go b/go/vt/vtctl/query.go index 8faf4f01684..cab44b5ed88 100644 --- a/go/vt/vtctl/query.go +++ b/go/vt/vtctl/query.go @@ -445,6 +445,13 @@ func (lw loggerWriter) Write(p []byte) (int, error) { // printQueryResult will pretty-print a QueryResult to the logger. func printQueryResult(writer io.Writer, qr *sqltypes.Result) { + if qr == nil { + return + } + if len(qr.Rows) == 0 { + return + } + table := tablewriter.NewWriter(writer) table.SetAutoFormatHeaders(false) diff --git a/go/vt/vtctl/vtctl.go b/go/vt/vtctl/vtctl.go index 412d032efe9..579d15ea68a 100644 --- a/go/vt/vtctl/vtctl.go +++ b/go/vt/vtctl/vtctl.go @@ -93,10 +93,6 @@ import ( "sync" "time" - "vitess.io/vitess/go/vt/log" - - querypb "vitess.io/vitess/go/vt/proto/query" - "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" "golang.org/x/net/context" @@ -108,7 +104,9 @@ import ( "vitess.io/vitess/go/sync2" hk "vitess.io/vitess/go/vt/hook" "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/logutil" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/schemamanager" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/topo" @@ -412,6 +410,17 @@ var commands = []commandGroup{ {"CopySchemaShard", commandCopySchemaShard, "[-tables=,,...] [-exclude_tables=,,...] [-include-views] [-skip-verify] [-wait_replicas_timeout=10s] { || } ", "Copies the schema from a source shard's master (or a specific tablet) to a destination shard. The schema is applied directly on the master of the destination shard, and it is propagated to the replicas through binlogs."}, + {"OnlineDDL", commandOnlineDDL, + " []", + "Operates on online DDL (migrations). Examples:" + + " \nvtctl OnlineDDL test_keyspace show 82fa54ac_e83e_11ea_96b7_f875a4d24e90" + + " \nvtctl OnlineDDL test_keyspace show all" + + " \nvtctl OnlineDDL test_keyspace show running" + + " \nvtctl OnlineDDL test_keyspace show complete" + + " \nvtctl OnlineDDL test_keyspace show failed" + + " \nvtctl OnlineDDL test_keyspace retry 82fa54ac_e83e_11ea_96b7_f875a4d24e90" + + " \nvtctl OnlineDDL test_keyspace cancel 82fa54ac_e83e_11ea_96b7_f875a4d24e90", + }, {"ValidateVersionShard", commandValidateVersionShard, "", @@ -2434,6 +2443,77 @@ func commandApplySchema(ctx context.Context, wr *wrangler.Wrangler, subFlags *fl ) } +func commandOnlineDDL(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { + if err := subFlags.Parse(args); err != nil { + return err + } + if subFlags.NArg() < 1 { + return fmt.Errorf("the argument is required for the OnlineDDL command") + } + keyspace := subFlags.Args()[0] + if subFlags.NArg() < 2 { + return fmt.Errorf("the argument is required for the OnlineDDL command") + } + command := subFlags.Args()[1] + arg := "" + if subFlags.NArg() >= 3 { + arg = subFlags.Args()[2] + } + query := "" + uuid := "" + switch command { + case "show": + { + condition := "" + switch arg { + case "", "all": + condition = "migration_uuid like '%'" + case "recent": + condition = "requested_timestamp > now() - interval 1 week" + case + string(schema.OnlineDDLStatusCancelled), + string(schema.OnlineDDLStatusQueued), + string(schema.OnlineDDLStatusReady), + string(schema.OnlineDDLStatusRunning), + string(schema.OnlineDDLStatusComplete), + string(schema.OnlineDDLStatusFailed): + condition = fmt.Sprintf("migration_status='%s'", arg) + default: + uuid = arg + condition = fmt.Sprintf("migration_uuid='%s'", uuid) + } + query = fmt.Sprintf(`select + shard, mysql_schema, mysql_table, migration_uuid, strategy, started_timestamp, completed_timestamp, migration_status + from _vt.schema_migrations where %s`, condition) + } + case "retry": + { + if arg == "" { + return fmt.Errorf("UUID required") + } + uuid = arg + query = fmt.Sprintf(`update _vt.schema_migrations set migration_status='retry' where migration_uuid='%s'`, uuid) + } + case "cancel": + { + if arg == "" { + return fmt.Errorf("UUID required") + } + uuid = arg + query = fmt.Sprintf(`update _vt.schema_migrations set migration_status='cancel' where migration_uuid='%s'`, uuid) + } + default: + return fmt.Errorf("Unknown OnlineDDL command: %s", command) + } + + qr, err := wr.VExecResult(ctx, uuid, keyspace, query, false) + if err != nil { + return err + } + printQueryResult(loggerWriter{wr.Logger()}, qr) + return nil +} + func commandCopySchemaShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { tables := subFlags.String("tables", "", "Specifies a comma-separated list of tables to copy. Each is either an exact match, or a regular expression of the form /regexp/") excludeTables := subFlags.String("exclude_tables", "", "Specifies a comma-separated list of tables to exclude. Each is either an exact match, or a regular expression of the form /regexp/") @@ -2874,30 +2954,16 @@ func commandVExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Fla } query := subFlags.Arg(1) - results, err := wr.VExec(ctx, workflow, keyspace, query, *dryRun) + qr, err := wr.VExecResult(ctx, workflow, keyspace, query, *dryRun) if err != nil { return err } if *dryRun { return nil } - if len(results) == 0 { + if qr == nil { wr.Logger().Printf("no result returned\n") } - var qr *sqltypes.Result - var numFields int - for _, result := range results { - numFields = len(result.Fields) - break - } - if numFields != 0 { - qr = queryResultForTabletResults(results) - } else { - qr = queryResultForRowsAffected(results) - } - if len(qr.Rows) == 0 { - return nil - } if *json { return printJSON(wr.Logger(), qr) } @@ -2905,49 +2971,6 @@ func commandVExec(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.Fla return nil } -// called for workflow stop/start/delete. Only rows affected are reported per tablet -func queryResultForRowsAffected(results map[*topo.TabletInfo]*sqltypes.Result) *sqltypes.Result { - var qr = &sqltypes.Result{} - qr.RowsAffected = uint64(len(results)) - qr.Fields = []*querypb.Field{{ - Name: "Tablet", - Type: sqltypes.VarBinary, - }, { - Name: "RowsAffected", - Type: sqltypes.Uint64, - }} - var row2 []sqltypes.Value - for tablet, result := range results { - row2 = nil - row2 = append(row2, sqltypes.NewVarBinary(tablet.AliasString())) - row2 = append(row2, sqltypes.NewUint64(result.RowsAffected)) - qr.Rows = append(qr.Rows, row2) - } - return qr -} - -func queryResultForTabletResults(results map[*topo.TabletInfo]*sqltypes.Result) *sqltypes.Result { - var qr = &sqltypes.Result{} - qr.RowsAffected = uint64(len(results)) - qr.Fields = []*querypb.Field{{ - Name: "Tablet", - Type: sqltypes.VarBinary, - }} - var row2 []sqltypes.Value - for tablet, result := range results { - for _, row := range result.Rows { - if len(qr.Fields) == 1 { - qr.Fields = append(qr.Fields, result.Fields...) - } - row2 = nil - row2 = append(row2, sqltypes.NewVarBinary(tablet.AliasString())) - row2 = append(row2, row...) - qr.Rows = append(qr.Rows, row2) - } - } - return qr -} - func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { dryRun := subFlags.Bool("dry_run", false, "Does a dry run of Workflow and only reports the final query and list of masters on which the operation will be applied") if err := subFlags.Parse(args); err != nil { @@ -2986,7 +3009,7 @@ func commandWorkflow(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag. wr.Logger().Printf("no result returned\n") return nil } - qr := queryResultForRowsAffected(results) + qr := wr.QueryResultForRowsAffected(results) printQueryResult(loggerWriter{wr.Logger()}, qr) return nil diff --git a/go/vt/vtctld/api.go b/go/vt/vtctld/api.go index 28663876e3e..1b25263096f 100644 --- a/go/vt/vtctld/api.go +++ b/go/vt/vtctld/api.go @@ -628,7 +628,8 @@ func initAPI(ctx context.Context, ts *topo.Server, actions *ActionRepository, re wr := wrangler.New(logger, ts, tmClient) executor := schemamanager.NewTabletExecutor( - wr, time.Duration(req.ReplicaTimeoutSeconds)*time.Second) + wr, time.Duration(req.ReplicaTimeoutSeconds)*time.Second, + ) return schemamanager.Run(ctx, schemamanager.NewUIController(req.SQL, req.Keyspace, w), executor) diff --git a/go/vt/vtctld/schema.go b/go/vt/vtctld/schema.go new file mode 100644 index 00000000000..299b21b651c --- /dev/null +++ b/go/vt/vtctld/schema.go @@ -0,0 +1,186 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vtctld + +import ( + "flag" + "fmt" + "sync" + "time" + + "golang.org/x/net/context" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/timer" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/logutil" + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/servenv" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vttablet/tmclient" + "vitess.io/vitess/go/vt/wrangler" +) + +var ( + migrationCheckTicks *timer.Timer + onlineDDLOnce sync.Once +) + +var ( + migrationCheckInterval = flag.Duration("online_ddl_check_interval", time.Minute, "interval polling for new online DDL requests") +) + +func initSchemaManager(ts *topo.Server) { + tmClient := tmclient.NewTabletManagerClient() + migrationCheckTicks = timer.NewTimer(*migrationCheckInterval) + + runMigrationRequestChecks(ts, tmClient) +} + +func runMigrationRequestChecks(ts *topo.Server, tmClient tmclient.TabletManagerClient) { + ctx, cancel := context.WithCancel(context.Background()) + migrationCheckTicks.Start(func() { onMigrationCheckTick(ctx, ts, tmClient) }) + + go func() { + <-ctx.Done() + migrationCheckTicks.Stop() + }() + + // Running cancel on OnTermSync will cancel the context of any + // running workflow inside vtctld. They may still checkpoint + // if they want to. + servenv.OnTermSync(cancel) +} + +func reviewMigrationRequest(ctx context.Context, ts *topo.Server, tmClient tmclient.TabletManagerClient, conn topo.Conn, uuid string) error { + if !schema.IsOnlineDDLUUID(uuid) { + // Just some other entry in this path, e.g. a sentry or a placeholder. + return nil + } + entryPath := fmt.Sprintf("%s/%s", schema.MigrationRequestsPath(), uuid) + onlineDDL, err := schema.ReadTopo(ctx, conn, entryPath) + if err != nil { + return err + } + log.Infof("Found schema migration request: %+v", onlineDDL) + + onlineDDL.Status = schema.OnlineDDLStatusQueued + + logstream := logutil.NewMemoryLogger() + wr := wrangler.New(logstream, ts, tmClient) + + sqlInsertSchemaMigration := `INSERT IGNORE INTO %s.schema_migrations ( + migration_uuid, + keyspace, + shard, + mysql_schema, + mysql_table, + migration_statement, + strategy, + options, + requested_timestamp, + migration_status + ) VALUES ( + %a, %a, %a, %a, %a, %a, %a, %a, FROM_UNIXTIME(%a), %a + )` + parsed := sqlparser.BuildParsedQuery(sqlInsertSchemaMigration, "_vt", + ":migration_uuid", + ":keyspace", + ":shard", + ":mysql_schema", + ":mysql_table", + ":migration_statement", + ":strategy", + ":options", + ":requested_timestamp", + ":migration_status", + ) + bindVars := map[string]*querypb.BindVariable{ + "migration_uuid": sqltypes.StringBindVariable(onlineDDL.UUID), + "keyspace": sqltypes.StringBindVariable(onlineDDL.Keyspace), + "shard": sqltypes.StringBindVariable(""), + "mysql_schema": sqltypes.StringBindVariable(""), + "mysql_table": sqltypes.StringBindVariable(onlineDDL.Table), + "migration_statement": sqltypes.StringBindVariable(onlineDDL.SQL), + "strategy": sqltypes.StringBindVariable(string(onlineDDL.Strategy)), + "options": sqltypes.StringBindVariable(onlineDDL.Options), + "requested_timestamp": sqltypes.Int64BindVariable(onlineDDL.RequestTimeSeconds()), + "migration_status": sqltypes.StringBindVariable(string(onlineDDL.Status)), + } + + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + + _, err = wr.VExecResult(ctx, onlineDDL.UUID, onlineDDL.Keyspace, bound, false) + if err != nil { + return err + } + + if err := onlineDDL.WriteTopo(ctx, conn, schema.MigrationQueuedPath()); err != nil { + return fmt.Errorf("unable to write reviewed migration: %+v, error: %s", onlineDDL, err) + } + if err := conn.Delete(ctx, entryPath, nil); err != nil { + return fmt.Errorf("unable to delete %+v, error: %s", entryPath, err) + } + return nil +} + +func reviewMigrationRequests(ctx context.Context, ts *topo.Server, tmClient tmclient.TabletManagerClient, conn topo.Conn) error { + entries, err := conn.ListDir(ctx, schema.MigrationRequestsPath(), true) + if err != nil { + log.Errorf("vtctld.reviewMigrationRequests listDir error: %s", err.Error()) + return err + } + + for _, entry := range entries { + if err := reviewMigrationRequest(ctx, ts, tmClient, conn, entry.Name); err != nil { + log.Errorf("vtctld.reviewMigrationRequest %s error: %s", entry.Name, err.Error()) + continue + } + } + return nil +} + +func onMigrationCheckTick(ctx context.Context, ts *topo.Server, tmClient tmclient.TabletManagerClient) { + conn, err := ts.ConnForCell(ctx, topo.GlobalCell) + if err != nil { + log.Errorf("vtctld.onMigrationCheckTick ConnForCell error: %s", err.Error()) + return + } + + onlineDDLOnce.Do(func() { + // This creates the directory schema.MigrationRequestsPath(), once. + // From now on, we can ListDir() n that directory without errors, even if no migration has ever been created. + _, err := conn.Create(ctx, fmt.Sprintf("%s/sentry", schema.MigrationRequestsPath()), []byte{}) + if err != nil && !topo.IsErrType(err, topo.NodeExists) { + log.Errorf("vtctld.onMigrationCheckTick Create sentry error: %s", err.Error()) + } + }) + + lockDescriptor, err := conn.Lock(ctx, schema.MigrationRequestsPath(), "vtctld.onMigrationCheckTick") + if err != nil { + log.Errorf("vtctld.onMigrationCheckTick ConnForCell error: %s", err.Error()) + return + } + defer lockDescriptor.Unlock(ctx) + + reviewMigrationRequests(ctx, ts, tmClient, conn) +} diff --git a/go/vt/vtctld/vtctld.go b/go/vt/vtctld/vtctld.go index 7dde2434273..b0ebe52bd18 100644 --- a/go/vt/vtctld/vtctld.go +++ b/go/vt/vtctld/vtctld.go @@ -179,6 +179,9 @@ func InitVtctld(ts *topo.Server) { // Init workflow manager. initWorkflowManager(ts) + // Init online DDL schema manager + initSchemaManager(ts) + // Setup reverse proxy for all vttablets through /vttablet/. initVTTabletRedirection(ts) } diff --git a/go/vt/vtgate/engine/fake_vcursor_test.go b/go/vt/vtgate/engine/fake_vcursor_test.go index 84353584a4c..f0359f1870b 100644 --- a/go/vt/vtgate/engine/fake_vcursor_test.go +++ b/go/vt/vtgate/engine/fake_vcursor_test.go @@ -36,6 +36,7 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/srvtopo" querypb "vitess.io/vitess/go/vt/proto/query" @@ -179,6 +180,10 @@ func (t noopVCursor) ResolveDestinations(keyspace string, ids []*querypb.Value, panic("unimplemented") } +func (t noopVCursor) SubmitOnlineDDL(onlineDDl *schema.OnlineDDL) error { + panic("unimplemented") +} + var _ VCursor = (*loggingVCursor)(nil) var _ SessionActions = (*loggingVCursor)(nil) @@ -294,6 +299,11 @@ func (f *loggingVCursor) AutocommitApproval() bool { return true } +func (f *loggingVCursor) SubmitOnlineDDL(onlineDDL *schema.OnlineDDL) error { + f.log = append(f.log, fmt.Sprintf("SubmitOnlineDDL: %s", onlineDDL.ToString())) + return nil +} + func (f *loggingVCursor) ExecuteStandalone(query string, bindvars map[string]*querypb.BindVariable, rs *srvtopo.ResolvedShard) (*sqltypes.Result, error) { f.log = append(f.log, fmt.Sprintf("ExecuteStandalone %s %v %s %s", query, printBindVars(bindvars), rs.Target.Keyspace, rs.Target.Shard)) return f.nextResult() diff --git a/go/vt/vtgate/engine/online_ddl.go b/go/vt/vtgate/engine/online_ddl.go new file mode 100644 index 00000000000..c2e5aa0bad0 --- /dev/null +++ b/go/vt/vtgate/engine/online_ddl.go @@ -0,0 +1,106 @@ +/* +Copyright 2020 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package engine + +import ( + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/vt/proto/query" + querypb "vitess.io/vitess/go/vt/proto/query" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vtgate/vindexes" +) + +var _ Primitive = (*OnlineDDL)(nil) + +//OnlineDDL represents the instructions to perform an online schema change via vtctld +type OnlineDDL struct { + Keyspace *vindexes.Keyspace + DDL *sqlparser.DDL + SQL string + Strategy sqlparser.DDLStrategy + Options string + + noTxNeeded + + noInputs +} + +func (v *OnlineDDL) description() PrimitiveDescription { + return PrimitiveDescription{ + OperatorType: "OnlineDDL", + Keyspace: v.Keyspace, + Other: map[string]interface{}{ + "query": sqlparser.String(v.DDL), + }, + } +} + +//RouteType implements the Primitive interface +func (v *OnlineDDL) RouteType() string { + return "OnlineDDL" +} + +//GetKeyspaceName implements the Primitive interface +func (v *OnlineDDL) GetKeyspaceName() string { + return v.Keyspace.Name +} + +//GetTableName implements the Primitive interface +func (v *OnlineDDL) GetTableName() string { + return v.DDL.Table.Name.String() +} + +//Execute implements the Primitive interface +func (v *OnlineDDL) Execute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantfields bool) (result *sqltypes.Result, err error) { + onlineDDL, err := schema.NewOnlineDDL(v.GetKeyspaceName(), v.GetTableName(), v.SQL, v.Strategy, v.Options) + if err != nil { + return result, err + } + err = vcursor.SubmitOnlineDDL(onlineDDL) + if err != nil { + return result, err + } + + result = &sqltypes.Result{ + Fields: []*querypb.Field{ + { + Name: "uuid", + Type: sqltypes.VarChar, + }, + }, + Rows: [][]sqltypes.Value{ + { + sqltypes.NewVarChar(onlineDDL.UUID), + }, + }, + RowsAffected: 1, + } + return result, err +} + +//StreamExecute implements the Primitive interface +func (v *OnlineDDL) StreamExecute(vcursor VCursor, bindVars map[string]*query.BindVariable, wantields bool, callback func(*sqltypes.Result) error) error { + return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") // TODO: shlomi - have no idea if this should work +} + +//GetFields implements the Primitive interface +func (v *OnlineDDL) GetFields(vcursor VCursor, bindVars map[string]*query.BindVariable) (*sqltypes.Result, error) { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "not reachable") // TODO: shlomi - have no idea if this should work +} diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index 7cb39769e91..1a60881a9a6 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -29,6 +29,7 @@ import ( "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/srvtopo" querypb "vitess.io/vitess/go/vt/proto/query" @@ -83,6 +84,8 @@ type ( ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL) error + SubmitOnlineDDL(onlineDDl *schema.OnlineDDL) error + Session() SessionActions ExecuteLock(rs *srvtopo.ResolvedShard, query *querypb.BoundQuery) (*sqltypes.Result, error) diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index eddbee9cad2..8627377ec76 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -1111,7 +1111,7 @@ func (e *Executor) StreamExecute(ctx context.Context, method string, safeSession bindVars = make(map[string]*querypb.BindVariable) } query, comments := sqlparser.SplitMarginComments(sql) - vcursor, _ := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver) + vcursor, _ := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver, e.serv) vcursor.SetIgnoreMaxMemoryRows(true) switch stmtType { case sqlparser.StmtStream: @@ -1614,7 +1614,7 @@ func (e *Executor) prepare(ctx context.Context, safeSession *SafeSession, sql st func (e *Executor) handlePrepare(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, logStats *LogStats) ([]*querypb.Field, error) { // V3 mode. query, comments := sqlparser.SplitMarginComments(sql) - vcursor, _ := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver) + vcursor, _ := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver, e.serv) plan, err := e.getPlan( vcursor, query, diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 1337b90c722..aa0ec565906 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -1412,8 +1412,8 @@ func TestVSchemaStats(t *testing.T) { func TestGetPlanUnnormalized(t *testing.T) { r, _, _, _ := createLegacyExecutorEnv() - emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) - unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) + unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) logStats1 := NewLogStats(ctx, "Test", "", nil) query1 := "select * from music_user_map where id = 1" @@ -1471,7 +1471,7 @@ func TestGetPlanUnnormalized(t *testing.T) { func TestGetPlanCacheUnnormalized(t *testing.T) { r, _, _, _ := createLegacyExecutorEnv() - emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) query1 := "select * from music_user_map where id = 1" logStats1 := NewLogStats(ctx, "Test", "", nil) _, err := r.getPlan(emptyvc, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, true /* skipQueryPlanCache */, logStats1) @@ -1496,7 +1496,7 @@ func TestGetPlanCacheUnnormalized(t *testing.T) { // Skip cache using directive r, _, _, _ = createLegacyExecutorEnv() - unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) query1 = "insert /*vt+ SKIP_QUERY_PLAN_CACHE=1 */ into user(id) values (1), (2)" logStats1 = NewLogStats(ctx, "Test", "", nil) @@ -1514,7 +1514,7 @@ func TestGetPlanCacheUnnormalized(t *testing.T) { } // the target string will be resolved and become part of the plan cache key, which adds a new entry - ksIDVc1, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[deadbeef]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + ksIDVc1, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[deadbeef]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) _, err = r.getPlan(ksIDVc1, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, false, logStats1) require.NoError(t, err) if len(r.plans.Keys()) != 2 { @@ -1522,7 +1522,7 @@ func TestGetPlanCacheUnnormalized(t *testing.T) { } // the target string will be resolved and become part of the plan cache key, as it's an unsharded ks, it will be the same entry as above - ksIDVc2, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[beefdead]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + ksIDVc2, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[beefdead]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) _, err = r.getPlan(ksIDVc2, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, false, logStats1) require.NoError(t, err) if len(r.plans.Keys()) != 2 { @@ -1533,7 +1533,7 @@ func TestGetPlanCacheUnnormalized(t *testing.T) { func TestGetPlanCacheNormalized(t *testing.T) { r, _, _, _ := createLegacyExecutorEnv() r.normalize = true - emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) query1 := "select * from music_user_map where id = 1" logStats1 := NewLogStats(ctx, "Test", "", nil) _, err := r.getPlan(emptyvc, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, true /* skipQueryPlanCache */, logStats1) @@ -1558,7 +1558,7 @@ func TestGetPlanCacheNormalized(t *testing.T) { // Skip cache using directive r, _, _, _ = createLegacyExecutorEnv() r.normalize = true - unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) query1 = "insert /*vt+ SKIP_QUERY_PLAN_CACHE=1 */ into user(id) values (1), (2)" logStats1 = NewLogStats(ctx, "Test", "", nil) @@ -1576,7 +1576,7 @@ func TestGetPlanCacheNormalized(t *testing.T) { } // the target string will be resolved and become part of the plan cache key, which adds a new entry - ksIDVc1, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[deadbeef]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + ksIDVc1, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[deadbeef]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) _, err = r.getPlan(ksIDVc1, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, false, logStats1) require.NoError(t, err) if len(r.plans.Keys()) != 2 { @@ -1584,7 +1584,7 @@ func TestGetPlanCacheNormalized(t *testing.T) { } // the target string will be resolved and become part of the plan cache key, as it's an unsharded ks, it will be the same entry as above - ksIDVc2, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[beefdead]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + ksIDVc2, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "[beefdead]"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) _, err = r.getPlan(ksIDVc2, query1, makeComments(" /* comment */"), map[string]*querypb.BindVariable{}, false, logStats1) require.NoError(t, err) if len(r.plans.Keys()) != 2 { @@ -1595,8 +1595,8 @@ func TestGetPlanCacheNormalized(t *testing.T) { func TestGetPlanNormalized(t *testing.T) { r, _, _, _ := createLegacyExecutorEnv() r.normalize = true - emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) - unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver) + emptyvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) + unshardedvc, _ := newVCursorImpl(ctx, NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded + "@unknown"}), makeComments(""), r, nil, r.vm, r.VSchema(), r.resolver.resolver, nil) query1 := "select * from music_user_map where id = 1" query2 := "select * from music_user_map where id = 2" diff --git a/go/vt/vtgate/plan_execute.go b/go/vt/vtgate/plan_execute.go index 5b0b61425b0..fae574f0f98 100644 --- a/go/vt/vtgate/plan_execute.go +++ b/go/vt/vtgate/plan_execute.go @@ -45,7 +45,7 @@ func (e *Executor) newExecute(ctx context.Context, safeSession *SafeSession, sql } query, comments := sqlparser.SplitMarginComments(sql) - vcursor, err := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver) + vcursor, err := newVCursorImpl(ctx, safeSession, comments, e, logStats, e.vm, e.VSchema(), e.resolver.resolver, e.serv) if err != nil { return 0, nil, err } diff --git a/go/vt/vtgate/planbuilder/builder.go b/go/vt/vtgate/planbuilder/builder.go index c36cb98e1c7..4ef0b183c75 100644 --- a/go/vt/vtgate/planbuilder/builder.go +++ b/go/vt/vtgate/planbuilder/builder.go @@ -318,6 +318,9 @@ func createInstructionFor(query string, stmt sqlparser.Statement, vschema Contex if sqlparser.IsVschemaDDL(stmt) { return buildVSchemaDDLPlan(stmt, vschema) } + if sqlparser.IsOnlineSchemaDDL(stmt, query) { + return buildOnlineDDLPlan(query, stmt, vschema) + } return buildDDLPlan(query, stmt, vschema) case *sqlparser.Use: return buildUsePlan(stmt, vschema) diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go index b701efb25c4..f95b1b637a5 100644 --- a/go/vt/vtgate/planbuilder/ddl.go +++ b/go/vt/vtgate/planbuilder/ddl.go @@ -1,7 +1,10 @@ package planbuilder import ( + "fmt" + "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/vtgate/engine" ) @@ -27,6 +30,30 @@ func buildDDLPlan(sql string, in sqlparser.Statement, vschema ContextVSchema) (e }, nil } +func buildOnlineDDLPlan(query string, stmt *sqlparser.DDL, vschema ContextVSchema) (engine.Primitive, error) { + _, keyspace, _, err := vschema.TargetDestination(stmt.Table.Qualifier.String()) + if err != nil { + return nil, err + } + if stmt.OnlineHint == nil { + return nil, fmt.Errorf("Not an online DDL: %s", query) + } + switch stmt.OnlineHint.Strategy { + case schema.DDLStrategyGhost, schema.DDLStrategyPTOSC: // OK, do nothing + case schema.DDLStrategyNormal: + return nil, fmt.Errorf("Not an online DDL strategy") + default: + return nil, fmt.Errorf("Unknown online DDL strategy: '%v'", stmt.OnlineHint.Strategy) + } + return &engine.OnlineDDL{ + Keyspace: keyspace, + DDL: stmt, + SQL: query, + Strategy: stmt.OnlineHint.Strategy, + Options: stmt.OnlineHint.Options, + }, nil +} + func buildVSchemaDDLPlan(stmt *sqlparser.DDL, vschema ContextVSchema) (engine.Primitive, error) { _, keyspace, _, err := vschema.TargetDestination(stmt.Table.Qualifier.String()) if err != nil { diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index 56f8d132900..412a3d30e5c 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -29,6 +29,7 @@ import ( "vitess.io/vitess/go/vt/callerid" vschemapb "vitess.io/vitess/go/vt/proto/vschema" + "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/topotools" "vitess.io/vitess/go/vt/vtgate/vschemaacl" @@ -40,6 +41,7 @@ import ( "vitess.io/vitess/go/vt/key" "vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/srvtopo" + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/vindexes" @@ -86,6 +88,7 @@ type vcursorImpl struct { marginComments sqlparser.MarginComments executor iExecute resolver *srvtopo.Resolver + topoServer *topo.Server logStats *LogStats // rollbackOnPartialExec is set to true if any DML was successfully // executed. If there was a subsequent failure, the transaction @@ -137,7 +140,7 @@ func (vc *vcursorImpl) ExecuteVSchema(keyspace string, vschemaDDL *sqlparser.DDL // the query and supply it here. Trailing comments are typically sent by the application for various reasons, // including as identifying markers. So, they have to be added back to all queries that are executed // on behalf of the original query. -func newVCursorImpl(ctx context.Context, safeSession *SafeSession, marginComments sqlparser.MarginComments, executor *Executor, logStats *LogStats, vm VSchemaOperator, vschema *vindexes.VSchema, resolver *srvtopo.Resolver) (*vcursorImpl, error) { +func newVCursorImpl(ctx context.Context, safeSession *SafeSession, marginComments sqlparser.MarginComments, executor *Executor, logStats *LogStats, vm VSchemaOperator, vschema *vindexes.VSchema, resolver *srvtopo.Resolver, serv srvtopo.Server) (*vcursorImpl, error) { keyspace, tabletType, destination, err := parseDestinationTarget(safeSession.TargetString, vschema) if err != nil { return nil, err @@ -147,6 +150,13 @@ func newVCursorImpl(ctx context.Context, safeSession *SafeSession, marginComment if UsingLegacyGateway() && safeSession.InTransaction() && tabletType != topodatapb.TabletType_MASTER { return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "newVCursorImpl: transactions are supported only for master tablet types, current type: %v", tabletType) } + var ts *topo.Server + if serv != nil { + ts, err = serv.GetTopoServer() + if err != nil { + return nil, err + } + } return &vcursorImpl{ ctx: ctx, @@ -160,6 +170,7 @@ func newVCursorImpl(ctx context.Context, safeSession *SafeSession, marginComment resolver: resolver, vschema: vschema, vm: vm, + topoServer: ts, }, nil } @@ -464,6 +475,16 @@ func (vc *vcursorImpl) TabletType() topodatapb.TabletType { return vc.tabletType } +// SubmitOnlineDDL implements the VCursor interface +func (vc *vcursorImpl) SubmitOnlineDDL(onlineDDl *schema.OnlineDDL) error { + conn, err := vc.topoServer.ConnForCell(vc.ctx, topo.GlobalCell) + if err != nil { + return err + } + // Submit an online schema change by writing a migration request in topo + return onlineDDl.WriteTopo(vc.ctx, conn, schema.MigrationRequestsPath()) +} + func commentedShardQueries(shardQueries []*querypb.BoundQuery, marginComments sqlparser.MarginComments) []*querypb.BoundQuery { if marginComments.Leading == "" && marginComments.Trailing == "" { return shardQueries diff --git a/go/vt/vtgate/vcursor_impl_test.go b/go/vt/vtgate/vcursor_impl_test.go index d7e41eb72e7..ca728dfe445 100644 --- a/go/vt/vtgate/vcursor_impl_test.go +++ b/go/vt/vtgate/vcursor_impl_test.go @@ -182,7 +182,7 @@ func TestDestinationKeyspace(t *testing.T) { }} for _, tc := range tests { - impl, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: tc.targetString}), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, nil) + impl, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{TargetString: tc.targetString}), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, nil, nil) impl.vschema = tc.vschema dest, keyspace, tabletType, err := impl.TargetDestination(tc.qualifier) if tc.expectedError == "" { @@ -239,7 +239,7 @@ func TestSetTarget(t *testing.T) { for i, tc := range tests { t.Run(fmt.Sprintf("%d#%s", i, tc.targetString), func(t *testing.T) { - vc, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{InTransaction: true}), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, nil) + vc, _ := newVCursorImpl(context.Background(), NewSafeSession(&vtgatepb.Session{InTransaction: true}), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, nil, nil) vc.vschema = tc.vschema err := vc.SetTarget(tc.targetString) if tc.expectedError == "" { @@ -281,7 +281,7 @@ func TestPlanPrefixKey(t *testing.T) { t.Run(fmt.Sprintf("%d#%s", i, tc.targetString), func(t *testing.T) { ss := NewSafeSession(&vtgatepb.Session{InTransaction: false}) ss.SetTargetString(tc.targetString) - vc, err := newVCursorImpl(context.Background(), ss, sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, srvtopo.NewResolver(&fakeTopoServer{}, nil, "")) + vc, err := newVCursorImpl(context.Background(), ss, sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: tc.vschema}, tc.vschema, srvtopo.NewResolver(&fakeTopoServer{}, nil, ""), nil) require.NoError(t, err) vc.vschema = tc.vschema require.Equal(t, tc.expectedPlanPrefixKey, vc.planPrefixKey()) @@ -300,7 +300,7 @@ func TestFirstSortedKeyspace(t *testing.T) { ks3Schema.Keyspace.Name: ks3Schema, }} - vc, err := newVCursorImpl(context.Background(), NewSafeSession(nil), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: vschemaWith2KS}, vschemaWith2KS, srvtopo.NewResolver(&fakeTopoServer{}, nil, "")) + vc, err := newVCursorImpl(context.Background(), NewSafeSession(nil), sqlparser.MarginComments{}, nil, nil, &fakeVSchemaOperator{vschema: vschemaWith2KS}, vschemaWith2KS, srvtopo.NewResolver(&fakeTopoServer{}, nil, ""), nil) require.NoError(t, err) ks, err := vc.FirstSortedKeyspace() require.NoError(t, err) diff --git a/go/vt/vttablet/faketmclient/fake_client.go b/go/vt/vttablet/faketmclient/fake_client.go index 25500ac2775..38229216c97 100644 --- a/go/vt/vttablet/faketmclient/fake_client.go +++ b/go/vt/vttablet/faketmclient/fake_client.go @@ -231,6 +231,15 @@ func (client *FakeTabletManagerClient) WaitForPosition(ctx context.Context, tabl return nil } +func (c *FakeTabletManagerClient) VExec(ctx context.Context, tablet *topodatapb.Tablet, query, workflow, keyspace string) (*querypb.QueryResult, error) { + // This result satisfies a generic VExec command + result := sqltypes.MakeTestResult( + sqltypes.MakeTestFields("id", "int"), + "complete", + ) + return sqltypes.ResultToProto3(result), nil +} + // VReplicationExec is part of the tmclient.TabletManagerClient interface. func (client *FakeTabletManagerClient) VReplicationExec(ctx context.Context, tablet *topodatapb.Tablet, query string) (*querypb.QueryResult, error) { // This result satisfies 'select pos from _vt.vreplication...' called from split clone unit tests in go/vt/worker. diff --git a/go/vt/vttablet/grpctmclient/client.go b/go/vt/vttablet/grpctmclient/client.go index 48be10a8b9d..0fb61207ef1 100644 --- a/go/vt/vttablet/grpctmclient/client.go +++ b/go/vt/vttablet/grpctmclient/client.go @@ -574,6 +574,19 @@ func (client *Client) GetReplicas(ctx context.Context, tablet *topodatapb.Tablet return response.Addrs, nil } +func (client *Client) VExec(ctx context.Context, tablet *topodatapb.Tablet, query, workflow, keyspace string) (*querypb.QueryResult, error) { + cc, c, err := client.dial(tablet) + if err != nil { + return nil, err + } + defer cc.Close() + response, err := c.VExec(ctx, &tabletmanagerdatapb.VExecRequest{Query: query, Workflow: workflow, Keyspace: keyspace}) + if err != nil { + return nil, err + } + return response.Result, nil +} + // VReplicationExec is part of the tmclient.TabletManagerClient interface. func (client *Client) VReplicationExec(ctx context.Context, tablet *topodatapb.Tablet, query string) (*querypb.QueryResult, error) { cc, c, err := client.dial(tablet) diff --git a/go/vt/vttablet/grpctmserver/server.go b/go/vt/vttablet/grpctmserver/server.go index ddab182cfc8..8e7bb1c9da5 100644 --- a/go/vt/vttablet/grpctmserver/server.go +++ b/go/vt/vttablet/grpctmserver/server.go @@ -317,6 +317,14 @@ func (s *server) GetReplicas(ctx context.Context, request *tabletmanagerdatapb.G return response, err } +func (s *server) VExec(ctx context.Context, request *tabletmanagerdatapb.VExecRequest) (response *tabletmanagerdatapb.VExecResponse, err error) { + defer s.tm.HandleRPCPanic(ctx, "VExec", request, response, true /*verbose*/, &err) + ctx = callinfo.GRPCCallInfo(ctx) + response = &tabletmanagerdatapb.VExecResponse{} + response.Result, err = s.tm.VExec(ctx, request.Query, request.Workflow, request.Keyspace) + return response, err +} + func (s *server) VReplicationExec(ctx context.Context, request *tabletmanagerdatapb.VReplicationExecRequest) (response *tabletmanagerdatapb.VReplicationExecResponse, err error) { defer s.tm.HandleRPCPanic(ctx, "VReplicationExec", request, response, true /*verbose*/, &err) ctx = callinfo.GRPCCallInfo(ctx) diff --git a/go/vt/vttablet/onlineddl/executor.go b/go/vt/vttablet/onlineddl/executor.go new file mode 100644 index 00000000000..1d6b3406a21 --- /dev/null +++ b/go/vt/vttablet/onlineddl/executor.go @@ -0,0 +1,1349 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package onlineddl + +import ( + "context" + "errors" + "flag" + "fmt" + "io/ioutil" + "math" + "os" + "path" + "strconv" + "strings" + "sync" + "sync/atomic" + "syscall" + "time" + + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/textutil" + "vitess.io/vitess/go/timer" + "vitess.io/vitess/go/vt/dbconnpool" + "vitess.io/vitess/go/vt/log" + "vitess.io/vitess/go/vt/schema" + "vitess.io/vitess/go/vt/servenv" + "vitess.io/vitess/go/vt/sqlparser" + "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" + "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" + "vitess.io/vitess/go/vt/vttablet/vexec" + + querypb "vitess.io/vitess/go/vt/proto/query" + topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" +) + +var ( + // ErrExecutorNotWritableTablet is generated when executor is asked to run gh-ost on a read-only server + ErrExecutorNotWritableTablet = errors.New("Cannot run gh-ost migration on non-writable tablet") + // ErrExecutorMigrationAlreadyRunning is generated when an attempt is made to run an operation that conflicts with a running migration + ErrExecutorMigrationAlreadyRunning = errors.New("Cannot run gh-ost migration since a migration is already running") + // ErrMigrationNotFound is returned by readMigration when given UUI cannot be found + ErrMigrationNotFound = errors.New("Migration not found") +) + +var vexecUpdateTemplates = []string{ + `update _vt.schema_migrations set migration_status='val' where migration_uuid='val' and mysql_schema='val'`, + `update _vt.schema_migrations set migration_status='val' where migration_uuid='val' and mysql_schema='val' and shard='val'`, +} + +var vexecInsertTemplates = []string{ + `INSERT IGNORE INTO _vt.schema_migrations ( + migration_uuid, + keyspace, + shard, + mysql_schema, + mysql_table, + migration_statement, + strategy, + options, + requested_timestamp, + migration_status + ) VALUES ( + 'val', 'val', 'val', 'val', 'val', 'val', 'val', 'val', FROM_UNIXTIME(0), 'val' + )`, +} + +var emptyResult = &sqltypes.Result{ + RowsAffected: 0, +} + +var ghostOverridePath = flag.String("gh-ost-path", "", "override default gh-ost binary full path") +var ptOSCOverridePath = flag.String("pt-osc-path", "", "override default pt-online-schema-change binary full path") +var migrationCheckInterval = flag.Duration("migration_check_interval", 1*time.Minute, "Interval between migration checks") + +const ( + maxPasswordLength = 32 // MySQL's *replication* password may not exceed 32 characters + staleMigrationMinutes = 10 +) + +var ( + migrationLogFileName = "migration.log" + onlineDDLUser = "vt-online-ddl-internal" + onlineDDLGrant = fmt.Sprintf("'%s'@'%s'", onlineDDLUser, "%") +) + +// Executor wraps and manages the execution of a gh-ost migration. +type Executor struct { + env tabletenv.Env + pool *connpool.Pool + tabletTypeFunc func() topodatapb.TabletType + ts *topo.Server + + keyspace string + shard string + dbName string + + initMutex sync.Mutex + migrationMutex sync.Mutex + migrationRunning int64 + lastMigrationUUID string + + ticks *timer.Timer + isOpen bool +} + +// GhostBinaryFileName returns the full path+name of the gh-ost binary +func GhostBinaryFileName() (fileName string, isOverride bool) { + if *ghostOverridePath != "" { + return *ghostOverridePath, true + } + return path.Join(os.TempDir(), "vt-gh-ost"), false +} + +// PTOSCFileName returns the full path+name of the pt-online-schema-change binary +// Note that vttablet does not include pt-online-schema-change +func PTOSCFileName() (fileName string, isOverride bool) { + if *ptOSCOverridePath != "" { + return *ptOSCOverridePath, true + } + return "/usr/bin/pt-online-schema-change", false +} + +// NewExecutor creates a new gh-ost executor. +func NewExecutor(env tabletenv.Env, ts *topo.Server, tabletTypeFunc func() topodatapb.TabletType) *Executor { + return &Executor{ + env: env, + + pool: connpool.NewPool(env, "ExecutorPool", tabletenv.ConnPoolConfig{ + Size: 1, + IdleTimeoutSeconds: env.Config().OltpReadPool.IdleTimeoutSeconds, + }), + tabletTypeFunc: tabletTypeFunc, + ts: ts, + ticks: timer.NewTimer(*migrationCheckInterval), + } +} + +func (e *Executor) execQuery(ctx context.Context, query string) (result *sqltypes.Result, err error) { + defer e.env.LogError() + + conn, err := e.pool.Get(ctx) + if err != nil { + return result, err + } + defer conn.Recycle() + return conn.Exec(ctx, query, math.MaxInt32, true) +} + +func (e *Executor) initSchema(ctx context.Context) error { + defer e.env.LogError() + + conn, err := e.pool.Get(ctx) + if err != nil { + return err + } + defer conn.Recycle() + parsed := sqlparser.BuildParsedQuery(sqlValidationQuery, "_vt") + _, err = withDDL.Exec(ctx, parsed.Query, conn.Exec) + return err +} + +// InitDBConfig initializes keysapce +func (e *Executor) InitDBConfig(keyspace, shard, dbName string) { + e.keyspace = keyspace + e.shard = shard + e.dbName = dbName +} + +// Open opens database pool and initializes the schema +func (e *Executor) Open() error { + e.initMutex.Lock() + defer e.initMutex.Unlock() + if e.isOpen { + return nil + } + e.pool.Open(e.env.Config().DB.AppWithDB(), e.env.Config().DB.DbaWithDB(), e.env.Config().DB.AppDebugWithDB()) + e.initSchema(context.Background()) + e.ticks.Start(e.onMigrationCheckTick) + + if _, err := sqlparser.QueryMatchesTemplates("select 1 from dual", vexecUpdateTemplates); err != nil { + // this validates vexecUpdateTemplates + return err + } + + e.isOpen = true + + return nil +} + +// Close frees resources +func (e *Executor) Close() { + e.initMutex.Lock() + defer e.initMutex.Unlock() + if !e.isOpen { + return + } + + e.ticks.Stop() + e.pool.Close() + e.isOpen = false +} + +func (e *Executor) ghostPanicFlagFileName(uuid string) string { + return path.Join(os.TempDir(), fmt.Sprintf("ghost.%s.panic.flag", uuid)) +} + +func (e *Executor) createGhostPanicFlagFile(uuid string) error { + _, err := os.Create(e.ghostPanicFlagFileName(uuid)) + return err +} +func (e *Executor) deleteGhostPanicFlagFile(uuid string) error { + // We use RemoveAll because if the file does not exist that's fine. Remove will return an error + // if file does not exist; RemoveAll does not. + return os.RemoveAll(e.ghostPanicFlagFileName(uuid)) +} + +func (e *Executor) ptPidFileName(uuid string) string { + return path.Join(os.TempDir(), fmt.Sprintf("pt-online-schema-change.%s.pid", uuid)) +} + +// readMySQLVariables contacts the backend MySQL server to read some of its configuration +func (e *Executor) readMySQLVariables(ctx context.Context) (host string, port int, readOnly bool, err error) { + conn, err := e.pool.Get(ctx) + if err != nil { + return host, port, readOnly, err + } + defer conn.Recycle() + + tm, err := conn.Exec(ctx, "select @@global.hostname as hostname, @@global.port as port, @@global.read_only as read_only from dual", 1, true) + if err != nil { + return host, port, readOnly, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "could not read MySQL variables: %v", err) + } + row := tm.Named().Row() + if row == nil { + return host, port, readOnly, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "unexpected result for MySQL variables: %+v", tm.Rows) + } + host = row["hostname"].ToString() + + p, err := row.ToInt64("port") + if err != nil { + return host, port, readOnly, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "could not parse @@global.port %v: %v", tm, err) + } + port = int(p) + + if readOnly, err = row.ToBool("read_only"); err != nil { + return host, port, readOnly, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "could not parse @@global.read_only %v: %v", tm, err) + } + return host, port, readOnly, nil +} + +// createOnlineDDLUser creates a gh-ost user account with all neccessary privileges and with a random password +func (e *Executor) createOnlineDDLUser(ctx context.Context) (password string, err error) { + conn, err := dbconnpool.NewDBConnection(ctx, e.env.Config().DB.DbaConnector()) + if err != nil { + return password, err + } + defer conn.Close() + + password = RandomHash()[0:maxPasswordLength] + + for _, query := range sqlCreateOnlineDDLUser { + parsed := sqlparser.BuildParsedQuery(query, onlineDDLGrant, password) + if _, err := conn.ExecuteFetch(parsed.Query, 0, false); err != nil { + return password, err + } + } + for _, query := range sqlGrantOnlineDDLUser { + parsed := sqlparser.BuildParsedQuery(query, onlineDDLGrant) + if _, err := conn.ExecuteFetch(parsed.Query, 0, false); err != nil { + return password, err + } + } + return password, err +} + +// dropOnlineDDLUser drops the given ddl user account at the end of migration +func (e *Executor) dropOnlineDDLUser(ctx context.Context) error { + conn, err := dbconnpool.NewDBConnection(ctx, e.env.Config().DB.DbaConnector()) + if err != nil { + return err + } + defer conn.Close() + + parsed := sqlparser.BuildParsedQuery(sqlDropOnlineDDLUser, onlineDDLGrant) + _, err = conn.ExecuteFetch(parsed.Query, 0, false) + return err +} + +// tableExists checks if a given table exists. +func (e *Executor) tableExists(ctx context.Context, tableName string) (bool, error) { + conn, err := e.pool.Get(ctx) + if err != nil { + return false, err + } + defer conn.Recycle() + + tableName = strings.ReplaceAll(tableName, `_`, `\_`) + parsed := sqlparser.BuildParsedQuery(sqlShowTablesLike, tableName) + rs, err := conn.Exec(ctx, parsed.Query, 1, true) + if err != nil { + return false, err + } + row := rs.Named().Row() + return (row != nil), nil +} + +// ExecuteWithGhost validates and runs a gh-ost process. +// Validation included testing the backend MySQL server and the gh-ost binary itself +// Execution runs first a dry run, then an actual migration +func (e *Executor) ExecuteWithGhost(ctx context.Context, onlineDDL *schema.OnlineDDL) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + if atomic.LoadInt64(&e.migrationRunning) > 0 { + return ErrExecutorMigrationAlreadyRunning + } + + if e.tabletTypeFunc() != topodatapb.TabletType_MASTER { + return ErrExecutorNotWritableTablet + } + mysqlHost, mysqlPort, readOnly, err := e.readMySQLVariables(ctx) + if err != nil { + log.Errorf("Error before running gh-ost: %+v", err) + return err + } + if readOnly { + err := fmt.Errorf("Error before running gh-ost: MySQL server is read_only") + log.Errorf(err.Error()) + return err + } + onlineDDLPassword, err := e.createOnlineDDLUser(ctx) + if err != nil { + err := fmt.Errorf("Error creating gh-ost user: %+v", err) + log.Errorf(err.Error()) + return err + } + tempDir, err := createTempDir(onlineDDL.UUID) + if err != nil { + log.Errorf("Error creating temporary directory: %+v", err) + return err + } + binaryFileName, _ := GhostBinaryFileName() + credentialsConfigFileContent := fmt.Sprintf(`[client] +user=%s +password=${ONLINE_DDL_PASSWORD} +`, onlineDDLUser) + credentialsConfigFileName, err := createTempScript(tempDir, "gh-ost-conf.cfg", credentialsConfigFileContent) + if err != nil { + log.Errorf("Error creating config file: %+v", err) + return err + } + wrapperScriptContent := fmt.Sprintf(`#!/bin/bash +ghost_log_path="%s" +ghost_log_file="%s" + +mkdir -p "$ghost_log_path" + +export ONLINE_DDL_PASSWORD +%s "$@" > "$ghost_log_path/$ghost_log_file" 2>&1 + `, tempDir, migrationLogFileName, binaryFileName, + ) + wrapperScriptFileName, err := createTempScript(tempDir, "gh-ost-wrapper.sh", wrapperScriptContent) + if err != nil { + log.Errorf("Error creating wrapper script: %+v", err) + return err + } + onHookContent := func(status schema.OnlineDDLStatus) string { + return fmt.Sprintf(`#!/bin/bash +curl -s 'http://localhost:%d/schema-migration/report-status?uuid=%s&status=%s&dryrun='"$GH_OST_DRY_RUN" + `, *servenv.Port, onlineDDL.UUID, string(status)) + } + if _, err := createTempScript(tempDir, "gh-ost-on-startup", onHookContent(schema.OnlineDDLStatusRunning)); err != nil { + log.Errorf("Error creating script: %+v", err) + return err + } + if _, err := createTempScript(tempDir, "gh-ost-on-status", onHookContent(schema.OnlineDDLStatusRunning)); err != nil { + log.Errorf("Error creating script: %+v", err) + return err + } + if _, err := createTempScript(tempDir, "gh-ost-on-success", onHookContent(schema.OnlineDDLStatusComplete)); err != nil { + log.Errorf("Error creating script: %+v", err) + return err + } + if _, err := createTempScript(tempDir, "gh-ost-on-failure", onHookContent(schema.OnlineDDLStatusFailed)); err != nil { + log.Errorf("Error creating script: %+v", err) + return err + } + serveSocketFile := path.Join(tempDir, "serve.sock") + + if err := e.deleteGhostPanicFlagFile(onlineDDL.UUID); err != nil { + log.Errorf("Error removing gh-ost panic flag file %s: %+v", e.ghostPanicFlagFileName(onlineDDL.UUID), err) + return err + } + // Validate gh-ost binary: + log.Infof("Will now validate gh-ost binary") + _, err = execCmd( + "bash", + []string{ + wrapperScriptFileName, + "--version", + }, + os.Environ(), + "/tmp", + nil, + nil, + ) + if err != nil { + log.Errorf("Error testing gh-ost binary: %+v", err) + return err + } + log.Infof("+ OK") + + if err := e.updateMigrationLogPath(ctx, onlineDDL.UUID, mysqlHost, tempDir); err != nil { + return err + } + + runGhost := func(execute bool) error { + // Temporary hack (2020-08-11) + // Because sqlparser does not do full blown ALTER TABLE parsing, + // and because we don't want gh-ost to know about WITH_GHOST and WITH_PT syntax, + // we resort to regexp-based parsing of the query. + // TODO(shlomi): generate _alter options_ via sqlparser when it full supports ALTER TABLE syntax. + _, _, alterOptions := schema.ParseAlterTableOptions(onlineDDL.SQL) + forceTableNames := fmt.Sprintf("%s_%s", onlineDDL.UUID, ReadableTimestamp()) + + if err := e.updateArtifacts(ctx, onlineDDL.UUID, + fmt.Sprintf("_%s_gho", forceTableNames), + fmt.Sprintf("_%s_ghc", forceTableNames), + fmt.Sprintf("_%s_del", forceTableNames), + ); err != nil { + return err + } + + os.Setenv("ONLINE_DDL_PASSWORD", onlineDDLPassword) + args := []string{ + wrapperScriptFileName, + fmt.Sprintf(`--host=%s`, mysqlHost), + fmt.Sprintf(`--port=%d`, mysqlPort), + fmt.Sprintf(`--conf=%s`, credentialsConfigFileName), // user & password found here + `--allow-on-master`, + `--max-load=Threads_running=900`, + `--critical-load=Threads_running=1000`, + `--critical-load-hibernate-seconds=60`, + `--approve-renamed-columns`, + `--debug`, + `--exact-rowcount`, + `--default-retries=120`, + fmt.Sprintf("--force-table-names=%s", forceTableNames), + fmt.Sprintf("--serve-socket-file=%s", serveSocketFile), + fmt.Sprintf("--hooks-path=%s", tempDir), + fmt.Sprintf(`--hooks-hint-token=%s`, onlineDDL.UUID), + fmt.Sprintf(`--throttle-http=http://localhost:%d/throttler/check`, *servenv.Port), + fmt.Sprintf(`--database=%s`, e.dbName), + fmt.Sprintf(`--table=%s`, onlineDDL.Table), + fmt.Sprintf(`--alter=%s`, alterOptions), + fmt.Sprintf(`--panic-flag-file=%s`, e.ghostPanicFlagFileName(onlineDDL.UUID)), + fmt.Sprintf(`--execute=%t`, execute), + } + args = append(args, strings.Fields(onlineDDL.Options)...) + _, err := execCmd("bash", args, os.Environ(), "/tmp", nil, nil) + return err + } + + atomic.StoreInt64(&e.migrationRunning, 1) + e.lastMigrationUUID = onlineDDL.UUID + + go func() error { + defer atomic.StoreInt64(&e.migrationRunning, 0) + defer e.dropOnlineDDLUser(ctx) + defer e.gcArtifacts(ctx) + + log.Infof("Will now dry-run gh-ost on: %s:%d", mysqlHost, mysqlPort) + if err := runGhost(false); err != nil { + // perhaps gh-ost was interrupted midway and didn't have the chance to send a "failes" status + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + log.Errorf("Error executing gh-ost dry run: %+v", err) + return err + } + log.Infof("+ OK") + + log.Infof("Will now run gh-ost on: %s:%d", mysqlHost, mysqlPort) + startedMigrations.Add(1) + if err := runGhost(true); err != nil { + // perhaps gh-ost was interrupted midway and didn't have the chance to send a "failes" status + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + failedMigrations.Add(1) + log.Errorf("Error running gh-ost: %+v", err) + return err + } + // Migration successful! + os.RemoveAll(tempDir) + successfulMigrations.Add(1) + log.Infof("+ OK") + return nil + }() + return nil +} + +// ExecuteWithPTOSC validates and runs a pt-online-schema-change process. +// Validation included testing the backend MySQL server and the pt-online-schema-change binary itself +// Execution runs first a dry run, then an actual migration +func (e *Executor) ExecuteWithPTOSC(ctx context.Context, onlineDDL *schema.OnlineDDL) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + if atomic.LoadInt64(&e.migrationRunning) > 0 { + return ErrExecutorMigrationAlreadyRunning + } + + if e.tabletTypeFunc() != topodatapb.TabletType_MASTER { + return ErrExecutorNotWritableTablet + } + mysqlHost, mysqlPort, readOnly, err := e.readMySQLVariables(ctx) + if err != nil { + log.Errorf("Error before running pt-online-schema-change: %+v", err) + return err + } + if readOnly { + err := fmt.Errorf("Error before running pt-online-schema-change: MySQL server is read_only") + log.Errorf(err.Error()) + return err + } + onlineDDLPassword, err := e.createOnlineDDLUser(ctx) + if err != nil { + err := fmt.Errorf("Error creating pt-online-schema-change user: %+v", err) + log.Errorf(err.Error()) + return err + } + tempDir, err := createTempDir(onlineDDL.UUID) + if err != nil { + log.Errorf("Error creating temporary directory: %+v", err) + return err + } + + binaryFileName, _ := PTOSCFileName() + wrapperScriptContent := fmt.Sprintf(`#!/bin/bash +pt_log_path="%s" +pt_log_file="%s" + +mkdir -p "$pt_log_path" + +export MYSQL_PWD +%s "$@" > "$pt_log_path/$pt_log_file" 2>&1 + `, tempDir, migrationLogFileName, binaryFileName, + ) + wrapperScriptFileName, err := createTempScript(tempDir, "pt-online-schema-change-wrapper.sh", wrapperScriptContent) + if err != nil { + log.Errorf("Error creating wrapper script: %+v", err) + return err + } + pluginCode := ` + package pt_online_schema_change_plugin; + + use strict; + use LWP::Simple; + + sub new { + my($class, % args) = @_; + my $self = { %args }; + return bless $self, $class; + } + + sub init { + my($self, % args) = @_; + } + + sub before_create_new_table { + my($self, % args) = @_; + get("http://localhost:{{VTTABLET_PORT}}/schema-migration/report-status?uuid={{MIGRATION_UUID}}&status={{OnlineDDLStatusRunning}}&dryrun={{DRYRUN}}"); + } + + sub before_exit { + my($self, % args) = @_; + my $exit_status = $args{exit_status}; + if ($exit_status == 0) { + get("http://localhost:{{VTTABLET_PORT}}/schema-migration/report-status?uuid={{MIGRATION_UUID}}&status={{OnlineDDLStatusComplete}}&dryrun={{DRYRUN}}"); + } else { + get("http://localhost:{{VTTABLET_PORT}}/schema-migration/report-status?uuid={{MIGRATION_UUID}}&status={{OnlineDDLStatusFailed}}&dryrun={{DRYRUN}}"); + } + } + + sub get_slave_lag { + my ($self, %args) = @_; + + return sub { + if (head("http://localhost:{{VTTABLET_PORT}}/throttler/check")) { + # Got HTTP 200 OK, means throttler is happy + return 0; + } else { + # Throttler requests to hold back + return 2147483647; # maxint, report *very* high lag + } + }; + } + + 1; + ` + pluginCode = strings.ReplaceAll(pluginCode, "{{VTTABLET_PORT}}", fmt.Sprintf("%d", *servenv.Port)) + pluginCode = strings.ReplaceAll(pluginCode, "{{MIGRATION_UUID}}", onlineDDL.UUID) + pluginCode = strings.ReplaceAll(pluginCode, "{{OnlineDDLStatusRunning}}", string(schema.OnlineDDLStatusRunning)) + pluginCode = strings.ReplaceAll(pluginCode, "{{OnlineDDLStatusComplete}}", string(schema.OnlineDDLStatusComplete)) + pluginCode = strings.ReplaceAll(pluginCode, "{{OnlineDDLStatusFailed}}", string(schema.OnlineDDLStatusFailed)) + + // Validate pt-online-schema-change binary: + log.Infof("Will now validate pt-online-schema-change binary") + _, err = execCmd( + "bash", + []string{ + wrapperScriptFileName, + "--version", + }, + os.Environ(), + "/tmp", + nil, + nil, + ) + if err != nil { + log.Errorf("Error testing pt-online-schema-change binary: %+v", err) + return err + } + log.Infof("+ OK") + + if err := e.updateMigrationLogPath(ctx, onlineDDL.UUID, mysqlHost, tempDir); err != nil { + return err + } + + // Temporary hack (2020-08-11) + // Because sqlparser does not do full blown ALTER TABLE parsing, + // and because pt-online-schema-change requires only the table options part of the ALTER TABLE statement, + // we resort to regexp-based parsing of the query. + // TODO(shlomi): generate _alter options_ via sqlparser when it full supports ALTER TABLE syntax. + _, _, alterOptions := schema.ParseAlterTableOptions(onlineDDL.SQL) + + // The following sleep() is temporary and artificial. Because we create a new user for this + // migration, and because we throttle by replicas, we need to wait for the replicas to be + // caught up with the new user creation. Otherwise, the OSC tools will fail connecting to the replicas... + // Once we have a built in throttling service , we will no longe rneed to have the OSC tools probe the + // replicas. Instead, they will consult with our throttling service. + // TODO(shlomi): replace/remove this when we have a proper throttling solution + time.Sleep(time.Second) + + runPTOSC := func(execute bool) error { + os.Setenv("MYSQL_PWD", onlineDDLPassword) + newTableName := fmt.Sprintf("_%s_%s_new", onlineDDL.UUID, ReadableTimestamp()) + + if err := e.updateArtifacts(ctx, onlineDDL.UUID, + fmt.Sprintf("_%s_old", onlineDDL.Table), + fmt.Sprintf("__%s_old", onlineDDL.Table), + newTableName, + ); err != nil { + return err + } + + executeFlag := "--dry-run" + if execute { + executeFlag = "--execute" + } + finalPluginCode := strings.ReplaceAll(pluginCode, "{{DRYRUN}}", fmt.Sprintf("%t", !execute)) + pluginFile, err := createTempScript(tempDir, "pt-online-schema-change-plugin", finalPluginCode) + if err != nil { + log.Errorf("Error creating script: %+v", err) + return err + } + args := []string{ + wrapperScriptFileName, + `--pid`, + e.ptPidFileName(onlineDDL.UUID), + `--plugin`, + pluginFile, + `--new-table-name`, + newTableName, + `--alter`, + alterOptions, + `--check-slave-lag`, // We use primary's identity so that pt-online-schema-change calls our lag plugin for exactly 1 server + fmt.Sprintf(`h=%s,P=%d,D=%s,t=%s,u=%s`, mysqlHost, mysqlPort, e.dbName, onlineDDL.Table, onlineDDLUser), + executeFlag, + fmt.Sprintf(`h=%s,P=%d,D=%s,t=%s,u=%s`, mysqlHost, mysqlPort, e.dbName, onlineDDL.Table, onlineDDLUser), + } + + if execute { + args = append(args, + `--no-drop-new-table`, + `--no-drop-old-table`, + ) + } + args = append(args, strings.Fields(onlineDDL.Options)...) + _, err = execCmd("bash", args, os.Environ(), "/tmp", nil, nil) + return err + } + + atomic.StoreInt64(&e.migrationRunning, 1) + e.lastMigrationUUID = onlineDDL.UUID + + go func() error { + defer atomic.StoreInt64(&e.migrationRunning, 0) + defer e.dropOnlineDDLUser(ctx) + defer e.gcArtifacts(ctx) + + log.Infof("Will now dry-run pt-online-schema-change on: %s:%d", mysqlHost, mysqlPort) + if err := runPTOSC(false); err != nil { + // perhaps pt-osc was interrupted midway and didn't have the chance to send a "failes" status + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + _ = e.updateMigrationTimestamp(ctx, "completed_timestamp", onlineDDL.UUID) + log.Errorf("Error executing pt-online-schema-change dry run: %+v", err) + return err + } + log.Infof("+ OK") + + log.Infof("Will now run pt-online-schema-change on: %s:%d", mysqlHost, mysqlPort) + startedMigrations.Add(1) + if err := runPTOSC(true); err != nil { + // perhaps pt-osc was interrupted midway and didn't have the chance to send a "failes" status + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + _ = e.updateMigrationTimestamp(ctx, "completed_timestamp", onlineDDL.UUID) + _ = e.dropPTOSCMigrationTriggers(ctx, onlineDDL) + failedMigrations.Add(1) + log.Errorf("Error running pt-online-schema-change: %+v", err) + return err + } + // Migration successful! + os.RemoveAll(tempDir) + successfulMigrations.Add(1) + log.Infof("+ OK") + return nil + }() + return nil +} + +func (e *Executor) readMigration(ctx context.Context, uuid string) (onlineDDL *schema.OnlineDDL, err error) { + + parsed := sqlparser.BuildParsedQuery(sqlSelectMigration, "_vt", ":migration_uuid") + bindVars := map[string]*querypb.BindVariable{ + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return onlineDDL, err + } + r, err := e.execQuery(ctx, bound) + if err != nil { + return onlineDDL, err + } + row := r.Named().Row() + if row == nil { + // No results + return nil, ErrMigrationNotFound + } + onlineDDL = &schema.OnlineDDL{ + Keyspace: row["keyspace"].ToString(), + Table: row["mysql_table"].ToString(), + Schema: row["mysql_schema"].ToString(), + SQL: row["migration_statement"].ToString(), + UUID: row["migration_uuid"].ToString(), + Strategy: sqlparser.DDLStrategy(row["strategy"].ToString()), + Options: row["options"].ToString(), + Status: schema.OnlineDDLStatus(row["migration_status"].ToString()), + } + return onlineDDL, nil +} + +// terminateMigration attempts to interrupt and hard-stop a running migration +func (e *Executor) terminateMigration(ctx context.Context, onlineDDL *schema.OnlineDDL, lastMigrationUUID string) (foundRunning bool, err error) { + if atomic.LoadInt64(&e.migrationRunning) > 0 { + // double check: is the running migration the very same one we wish to cancel? + if onlineDDL.UUID == lastMigrationUUID { + // assuming all goes well in next steps, we can already report that there has indeed been a migration + foundRunning = true + } + } + switch onlineDDL.Strategy { + case schema.DDLStrategyPTOSC: + // see if pt-osc is running (could have been executed by this vttablet or one that crashed in the past) + if running, pid, _ := e.isPTOSCMigrationRunning(ctx, onlineDDL.UUID); running { + foundRunning = true + // Because pt-osc doesn't offer much control, we take a brute force approach to killing it, + // revoking its privileges, and cleaning up its triggers. + if err := syscall.Kill(pid, syscall.SIGTERM); err != nil { + return foundRunning, nil + } + if err := syscall.Kill(pid, syscall.SIGKILL); err != nil { + return foundRunning, nil + } + if err := e.dropOnlineDDLUser(ctx); err != nil { + return foundRunning, nil + } + if err := e.dropPTOSCMigrationTriggers(ctx, onlineDDL); err != nil { + return foundRunning, nil + } + } + case schema.DDLStrategyGhost: + // gh-ost migrations are easy to kill: just touch their specific panic flag files. We trust + // gh-ost to terminate. No need to KILL it. And there's no trigger cleanup. + if err := e.createGhostPanicFlagFile(onlineDDL.UUID); err != nil { + return foundRunning, fmt.Errorf("Error cancelling migration, flag file error: %+v", err) + } + } + return foundRunning, nil +} + +// cancelMigration attempts to abort a scheduled or a running migration +func (e *Executor) cancelMigration(ctx context.Context, uuid string, terminateRunningMigration bool) (result *sqltypes.Result, err error) { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + var rowsAffected uint64 + + onlineDDL, err := e.readMigration(ctx, uuid) + if err != nil { + return nil, err + } + + switch onlineDDL.Status { + case schema.OnlineDDLStatusQueued, schema.OnlineDDLStatusReady: + if err := e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusCancelled); err != nil { + return nil, err + } + rowsAffected = 1 + } + + if terminateRunningMigration { + migrationFound, err := e.terminateMigration(ctx, onlineDDL, e.lastMigrationUUID) + if migrationFound { + rowsAffected = 1 + } + if err != nil { + return result, err + } + } + + result = &sqltypes.Result{ + RowsAffected: rowsAffected, + } + + return result, nil +} + +// scheduleNextMigration attemps to schedule a single migration to run next. +// possibly there's no migrations to run. Possibly there's a migration running right now, +// in which cases nothing happens. +func (e *Executor) scheduleNextMigration(ctx context.Context) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + if atomic.LoadInt64(&e.migrationRunning) > 0 { + return ErrExecutorMigrationAlreadyRunning + } + + { + parsed := sqlparser.BuildParsedQuery(sqlSelectCountReadyMigrations, "_vt") + r, err := e.execQuery(ctx, parsed.Query) + if err != nil { + return err + } + row := r.Named().Row() + countReady, err := row.ToInt64("count_ready") + if err != nil { + return err + } + if countReady > 0 { + // seems like there's already one migration that's good to go + return nil + } + } // Cool, seems like no migration is ready. Let's try and make a single 'queued' migration 'ready' + + parsed := sqlparser.BuildParsedQuery(sqlScheduleSingleMigration, "_vt") + _, err := e.execQuery(ctx, parsed.Query) + + return err +} + +func (e *Executor) runNextMigration(ctx context.Context) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + if atomic.LoadInt64(&e.migrationRunning) > 0 { + return ErrExecutorMigrationAlreadyRunning + } + + parsed := sqlparser.BuildParsedQuery(sqlSelectReadyMigration, "_vt") + r, err := e.execQuery(ctx, parsed.Query) + if err != nil { + return err + } + named := r.Named() + for i, row := range named.Rows { + onlineDDL := &schema.OnlineDDL{ + Keyspace: row["keyspace"].ToString(), + Table: row["mysql_table"].ToString(), + Schema: row["mysql_schema"].ToString(), + SQL: row["migration_statement"].ToString(), + UUID: row["migration_uuid"].ToString(), + Strategy: sqlparser.DDLStrategy(row["strategy"].ToString()), + Options: row["options"].ToString(), + Status: schema.OnlineDDLStatus(row["migration_status"].ToString()), + } + switch onlineDDL.Strategy { + case schema.DDLStrategyGhost: + go func() { + if err := e.ExecuteWithGhost(ctx, onlineDDL); err != nil { + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + } + }() + case schema.DDLStrategyPTOSC: + go func() { + if err := e.ExecuteWithPTOSC(ctx, onlineDDL); err != nil { + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + } + }() + default: + { + _ = e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed) + return fmt.Errorf("Unsupported strategy: %+v", onlineDDL.Strategy) + } + } + // the query should only ever return a single row at the most + // but let's make it also explicit here that we only run a single migration + if i == 0 { + break + } + } + return nil +} + +// isPTOSCMigrationRunning sees if pt-online-schema-change is running a specific migration, +// by examining its PID file +func (e *Executor) isPTOSCMigrationRunning(ctx context.Context, uuid string) (isRunning bool, pid int, err error) { + // Try and read its PID file: + content, err := ioutil.ReadFile(e.ptPidFileName(uuid)) + if err != nil { + // file probably does not exist (migration not running) + // or any other issue --> we can't confirm that the migration is actually running + return false, pid, err + } + contentString := strings.TrimSpace(string(content)) + // + pid, err = strconv.Atoi(contentString) + if err != nil { + // can't get the PID right. Can't confirm migration is running. + return false, pid, err + } + p, err := os.FindProcess(pid) + if err != nil { + // can't find the process. Can't confirm migration is running. + return false, pid, err + } + err = p.Signal(syscall.Signal(0)) + if err != nil { + // can't verify process is running. Can't confirm migration is running. + return false, pid, err + } + // AHA! We are able to confirm this pt-osc migration is actually running! + return true, pid, nil +} + +// dropOnlineDDLUser drops the given ddl user account at the end of migration +func (e *Executor) dropPTOSCMigrationTriggers(ctx context.Context, onlineDDL *schema.OnlineDDL) error { + conn, err := dbconnpool.NewDBConnection(ctx, e.env.Config().DB.DbaConnector()) + if err != nil { + return err + } + defer conn.Close() + + parsed := sqlparser.BuildParsedQuery(sqlSelectPTOSCMigrationTriggers, ":mysql_schema", ":mysql_table") + bindVars := map[string]*querypb.BindVariable{ + "mysql_schema": sqltypes.StringBindVariable(onlineDDL.Schema), + "mysql_table": sqltypes.StringBindVariable(onlineDDL.Table), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + r, err := e.execQuery(ctx, bound) + if err != nil { + return err + } + for _, row := range r.Named().Rows { + // iterate pt-osc triggers and drop them + triggerSchema := row.AsString("trigger_schema", "") + triggerName := row.AsString("trigger_name", "") + + dropParsed := sqlparser.BuildParsedQuery(sqlDropTrigger, triggerSchema, triggerName) + if _, err := conn.ExecuteFetch(dropParsed.Query, 0, false); err != nil { + return err + } + } + + return err +} + +// reviewRunningMigrations iterates migrations in 'running' state (there really should just be one that is +// actually running). +func (e *Executor) reviewRunningMigrations(ctx context.Context) (countRunnning int, err error) { + parsed := sqlparser.BuildParsedQuery(sqlSelectRunningMigrations, "_vt", ":strategy") + bindVars := map[string]*querypb.BindVariable{ + "strategy": sqltypes.StringBindVariable(string(schema.DDLStrategyPTOSC)), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return countRunnning, err + } + r, err := e.execQuery(ctx, bound) + if err != nil { + return countRunnning, err + } + for _, row := range r.Named().Rows { + // A pt-osc UUID is found which claims to be 'running'. Is it? + uuid := row["migration_uuid"].ToString() + // Since pt-osc doesn't have a "liveness" plugin entry point, we do it externally: + // if the process is alive, we update the `liveness_timestamp` for this migration. + if running, _, _ := e.isPTOSCMigrationRunning(ctx, uuid); running { + _ = e.updateMigrationTimestamp(ctx, "liveness_timestamp", uuid) + } + countRunnning++ + } + return countRunnning, err +} + +// reviewStaleMigrations marks as 'failed' migrations whose status is 'running' but which have +// shown no liveness in past X minutes +func (e *Executor) reviewStaleMigrations(ctx context.Context) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + parsed := sqlparser.BuildParsedQuery(sqlSelectStaleMigrations, "_vt", ":minutes") + bindVars := map[string]*querypb.BindVariable{ + "minutes": sqltypes.Int64BindVariable(staleMigrationMinutes), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + r, err := e.execQuery(ctx, bound) + if err != nil { + return err + } + for _, row := range r.Named().Rows { + uuid := row["migration_uuid"].ToString() + + onlineDDL, err := e.readMigration(ctx, uuid) + if err != nil { + return err + } + // If this is pt-osc migration, then it may have crashed without having its triggers cleaned up. + // make sure to drop them. + if onlineDDL.Strategy == schema.DDLStrategyPTOSC { + if err := e.dropPTOSCMigrationTriggers(ctx, onlineDDL); err != nil { + return err + } + } + if err := e.updateMigrationStatus(ctx, onlineDDL.UUID, schema.OnlineDDLStatusFailed); err != nil { + return err + } + } + + return nil +} + +// gcArtifacts garbage-collects migration artifacts from completed/failed migrations +func (e *Executor) gcArtifactTable(ctx context.Context, artifactTable string) error { + tableExists, err := e.tableExists(ctx, artifactTable) + if err != nil { + return err + } + if !tableExists { + return nil + } + renameStatement, _, err := schema.GenerateRenameStatement(artifactTable, schema.PurgeTableGCState, time.Now().UTC()) + if err != nil { + return err + } + conn, err := e.pool.Get(ctx) + if err != nil { + return err + } + defer conn.Recycle() + + _, err = conn.Exec(ctx, renameStatement, 1, true) + return err +} + +// gcArtifacts garbage-collects migration artifacts from completed/failed migrations +func (e *Executor) gcArtifacts(ctx context.Context) error { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + + parsed := sqlparser.BuildParsedQuery(sqlSelectUncollectedArtifacts, "_vt") + r, err := e.execQuery(ctx, parsed.Query) + if err != nil { + return err + } + for _, row := range r.Named().Rows { + uuid := row["migration_uuid"].ToString() + artifacts := row["artifacts"].ToString() + + artifactTables := textutil.SplitDelimitedList(artifacts) + for _, artifactTable := range artifactTables { + if err := e.gcArtifactTable(ctx, artifactTable); err != nil { + return err + } + log.Infof("Executor.gcArtifacts: renamed away artifact %s", artifactTable) + } + if err := e.updateMigrationTimestamp(ctx, "cleanup_timestamp", uuid); err != nil { + return err + } + } + + return nil +} + +// onMigrationCheckTick runs all migrations life cycle +func (e *Executor) onMigrationCheckTick() { + if e.tabletTypeFunc() != topodatapb.TabletType_MASTER { + return + } + if e.keyspace == "" { + log.Errorf("Executor.onMigrationCheckTick(): empty keyspace") + return + } + ctx := context.Background() + + if err := e.scheduleNextMigration(ctx); err != nil { + log.Error(err) + } + if err := e.runNextMigration(ctx); err != nil { + log.Error(err) + } + if _, err := e.reviewRunningMigrations(ctx); err != nil { + log.Error(err) + } + if err := e.reviewStaleMigrations(ctx); err != nil { + log.Error(err) + } + if err := e.gcArtifacts(ctx); err != nil { + log.Error(err) + } +} + +func (e *Executor) updateMigrationStartedTimestamp(ctx context.Context, uuid string) error { + parsed := sqlparser.BuildParsedQuery(sqlUpdateMigrationStartedTimestamp, "_vt", + ":migration_uuid", + ) + bindVars := map[string]*querypb.BindVariable{ + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + _, err = e.execQuery(ctx, bound) + return err +} + +func (e *Executor) updateMigrationTimestamp(ctx context.Context, timestampColumn string, uuid string) error { + parsed := sqlparser.BuildParsedQuery(sqlUpdateMigrationTimestamp, "_vt", timestampColumn, + ":migration_uuid", + ) + bindVars := map[string]*querypb.BindVariable{ + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + _, err = e.execQuery(ctx, bound) + return err +} + +func (e *Executor) updateMigrationLogPath(ctx context.Context, uuid string, hostname, path string) error { + logPath := fmt.Sprintf("%s:%s", hostname, path) + parsed := sqlparser.BuildParsedQuery(sqlUpdateMigrationLogPath, "_vt", + ":log_path", + ":migration_uuid", + ) + bindVars := map[string]*querypb.BindVariable{ + "log_path": sqltypes.StringBindVariable(logPath), + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + _, err = e.execQuery(ctx, bound) + return err +} + +func (e *Executor) updateArtifacts(ctx context.Context, uuid string, artifacts ...string) error { + bindArtifacts := strings.Join(artifacts, ",") + parsed := sqlparser.BuildParsedQuery(sqlUpdateArtifacts, "_vt", + ":artifacts", + ":migration_uuid", + ) + bindVars := map[string]*querypb.BindVariable{ + "artifacts": sqltypes.StringBindVariable(bindArtifacts), + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + _, err = e.execQuery(ctx, bound) + return err +} + +func (e *Executor) updateMigrationStatus(ctx context.Context, uuid string, status schema.OnlineDDLStatus) error { + parsed := sqlparser.BuildParsedQuery(sqlUpdateMigrationStatus, "_vt", + ":migration_status", + ":migration_uuid", + ) + bindVars := map[string]*querypb.BindVariable{ + "migration_status": sqltypes.StringBindVariable(string(status)), + "migration_uuid": sqltypes.StringBindVariable(uuid), + } + bound, err := parsed.GenerateQuery(bindVars, nil) + if err != nil { + return err + } + _, err = e.execQuery(ctx, bound) + return err +} + +func (e *Executor) retryMigration(ctx context.Context, whereExpr string) (result *sqltypes.Result, err error) { + e.migrationMutex.Lock() + defer e.migrationMutex.Unlock() + parsed := sqlparser.BuildParsedQuery(sqlRetryMigration, "_vt", whereExpr) + result, err = e.execQuery(ctx, parsed.Query) + return result, err +} + +// OnSchemaMigrationStatus is called by TabletServer's API, which is invoked by a running gh-ost migration's hooks. +func (e *Executor) OnSchemaMigrationStatus(ctx context.Context, uuidParam, statusParam, dryrunParam string) (err error) { + status := schema.OnlineDDLStatus(statusParam) + dryRun := (dryrunParam == "true") + + if dryRun && status != schema.OnlineDDLStatusFailed { + // We don't consider dry-run reports unless there's a failure + return nil + } + switch status { + case schema.OnlineDDLStatusReady: + { + err = e.updateMigrationTimestamp(ctx, "ready_timestamp", uuidParam) + } + case schema.OnlineDDLStatusRunning: + { + _ = e.updateMigrationStartedTimestamp(ctx, uuidParam) + err = e.updateMigrationTimestamp(ctx, "liveness_timestamp", uuidParam) + } + case schema.OnlineDDLStatusComplete: + { + _ = e.updateMigrationStartedTimestamp(ctx, uuidParam) + err = e.updateMigrationTimestamp(ctx, "completed_timestamp", uuidParam) + } + case schema.OnlineDDLStatusFailed: + { + _ = e.updateMigrationStartedTimestamp(ctx, uuidParam) + err = e.updateMigrationTimestamp(ctx, "completed_timestamp", uuidParam) + } + } + if err != nil { + return err + } + if err = e.updateMigrationStatus(ctx, uuidParam, status); err != nil { + return err + } + + return nil +} + +// VExec is called by a VExec invocation +func (e *Executor) VExec(ctx context.Context, vx *vexec.TabletVExec) (qr *querypb.QueryResult, err error) { + response := func(result *sqltypes.Result, err error) (*querypb.QueryResult, error) { + if err != nil { + return nil, err + } + return sqltypes.ResultToProto3(result), nil + } + + switch stmt := vx.Stmt.(type) { + case *sqlparser.Delete: + return nil, fmt.Errorf("DELETE statements not supported for this table. query=%s", vx.Query) + case *sqlparser.Select: + return response(e.execQuery(ctx, vx.Query)) + case *sqlparser.Insert: + match, err := sqlparser.QueryMatchesTemplates(vx.Query, vexecInsertTemplates) + if err != nil { + return nil, err + } + if !match { + return nil, fmt.Errorf("Query must match one of these templates: %s", strings.Join(vexecInsertTemplates, "; ")) + } + // Vexec naturally runs outside shard/schema context. It does not supply values for those columns. + // We can fill them in. + vx.ReplaceInsertColumnVal("shard", vx.ToStringVal(e.shard)) + vx.ReplaceInsertColumnVal("mysql_schema", vx.ToStringVal(e.dbName)) + return response(e.execQuery(ctx, vx.Query)) + case *sqlparser.Update: + match, err := sqlparser.QueryMatchesTemplates(vx.Query, vexecUpdateTemplates) + if err != nil { + return nil, err + } + if !match { + return nil, fmt.Errorf("Query must match one of these templates: %s", strings.Join(vexecUpdateTemplates, "; ")) + } + if shard, _ := vx.ColumnStringVal(vx.WhereCols, "shard"); shard != "" { + // shard is specified. + if shard != e.shard { + // specified shard is not _this_ shard. So we're skipping this UPDATE + return sqltypes.ResultToProto3(emptyResult), nil + } + } + statusVal, err := vx.ColumnStringVal(vx.UpdateCols, "migration_status") + if err != nil { + return nil, err + } + switch statusVal { + case retryMigrationHint: + return response(e.retryMigration(ctx, sqlparser.String(stmt.Where.Expr))) + case cancelMigrationHint: + uuid, err := vx.ColumnStringVal(vx.WhereCols, "migration_uuid") + if err != nil { + return nil, err + } + return response(e.cancelMigration(ctx, uuid, true)) + default: + return nil, fmt.Errorf("Unexpected value for migration_status: %v. Supported values are: %s, %s", + statusVal, retryMigrationHint, cancelMigrationHint) + } + default: + return nil, fmt.Errorf("No handler for this query: %s", vx.Query) + } +} diff --git a/go/vt/vttablet/onlineddl/ghost.go b/go/vt/vttablet/onlineddl/ghost.go new file mode 100644 index 00000000000..40234c87f9b --- /dev/null +++ b/go/vt/vttablet/onlineddl/ghost.go @@ -0,0 +1,39 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package heartbeat contains a writer and reader of heartbeats for a master-replica cluster. +// This is similar to Percona's pt-heartbeat, and is meant to supplement the information +// returned from SHOW SLAVE STATUS. In some circumstances, lag returned from SHOW SLAVE STATUS +// is incorrect and is at best only at 1 second resolution. The heartbeat package directly +// tests replication by writing a record with a timestamp on the master, and comparing that +// timestamp after reading it on the replica. This happens at the interval defined by heartbeat_interval. +// Note: the lag reported will be affected by clock drift, so it is recommended to run ntpd or similar. +// +// The data collected by the heartbeat package is made available in /debug/vars in counters prefixed by Heartbeat*. +// It's additionally used as a source for healthchecks and will impact the serving state of a tablet, if enabled. +// The heartbeat interval is purposefully kept distinct from the health check interval because lag measurement +// requires more frequent polling that the healthcheck typically is configured for. +package onlineddl + +import ( + "vitess.io/vitess/go/stats" +) + +var ( + startedMigrations = stats.NewCounter("StartedMigrations", "Count of initiated migrations") + successfulMigrations = stats.NewCounter("SuccessfulMigrations", "Count of successful migrations, a subset of StartedMigrations") + failedMigrations = stats.NewCounter("FailedMigrations", "Count of failed migrations, a subset of StartedMigrations") +) diff --git a/go/vt/vttablet/onlineddl/schema.go b/go/vt/vttablet/onlineddl/schema.go new file mode 100644 index 00000000000..ef145320ffd --- /dev/null +++ b/go/vt/vttablet/onlineddl/schema.go @@ -0,0 +1,207 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package onlineddl + +import ( + "fmt" + + "vitess.io/vitess/go/vt/withddl" +) + +const ( + // SchemaMigrationsTableName is used by VExec interceptor to call the correct handler + SchemaMigrationsTableName = "schema_migrations" + sqlCreateSidecarDB = "create database if not exists %s" + sqlCreateSchemaMigrationsTable = `CREATE TABLE IF NOT EXISTS %s.schema_migrations ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + migration_uuid varchar(64) NOT NULL, + keyspace varchar(256) NOT NULL, + shard varchar(256) NOT NULL, + mysql_schema varchar(128) NOT NULL, + mysql_table varchar(128) NOT NULL, + migration_statement text NOT NULL, + strategy varchar(128) NOT NULL, + options varchar(8192) NOT NULL, + added_timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + requested_timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + ready_timestamp timestamp NULL DEFAULT NULL, + started_timestamp timestamp NULL DEFAULT NULL, + liveness_timestamp timestamp NULL DEFAULT NULL, + completed_timestamp timestamp NULL DEFAULT NULL, + cleanup_timestamp timestamp NULL DEFAULT NULL, + migration_status varchar(128) NOT NULL, + log_path varchar(1024) NOT NULL, + artifacts varchar(1024) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY uuid_idx (migration_uuid), + KEY keyspace_shard_idx (keyspace,shard), + KEY status_idx (migration_status, liveness_timestamp), + KEY cleanup_status_idx (cleanup_timestamp, migration_status) + ) engine=InnoDB DEFAULT CHARSET=utf8mb4` + sqlValidationQuery = `select 1 from %s.schema_migrations limit 1` + sqlScheduleSingleMigration = `UPDATE %s.schema_migrations + SET + migration_status='ready', + ready_timestamp=NOW() + WHERE + migration_status='queued' + ORDER BY + requested_timestamp ASC + LIMIT 1 + ` + sqlUpdateMigrationStatus = `UPDATE %s.schema_migrations + SET migration_status=%a + WHERE + migration_uuid=%a + ` + sqlUpdateMigrationStartedTimestamp = `UPDATE %s.schema_migrations + SET started_timestamp=IFNULL(started_timestamp, NOW()) + WHERE + migration_uuid=%a + ` + sqlUpdateMigrationTimestamp = `UPDATE %s.schema_migrations + SET %s=NOW() + WHERE + migration_uuid=%a + ` + sqlUpdateMigrationLogPath = `UPDATE %s.schema_migrations + SET log_path=%a + WHERE + migration_uuid=%a + ` + sqlUpdateArtifacts = `UPDATE %s.schema_migrations + SET artifacts=%a + WHERE + migration_uuid=%a + ` + sqlRetryMigration = `UPDATE %s.schema_migrations + SET + migration_status='queued', + ready_timestamp=NULL, + started_timestamp=NULL, + liveness_timestamp=NULL, + completed_timestamp=NULL + WHERE + migration_status IN ('failed', 'cancelled') + AND (%s) + LIMIT 1 + ` + sqlSelectRunningMigrations = `SELECT + migration_uuid + FROM %s.schema_migrations + WHERE + migration_status='running' + AND strategy=%a + ` + sqlSelectCountReadyMigrations = `SELECT + count(*) as count_ready + FROM %s.schema_migrations + WHERE + migration_status='ready' + ` + sqlSelectStaleMigrations = `SELECT + migration_uuid + FROM %s.schema_migrations + WHERE + migration_status='running' + AND liveness_timestamp < NOW() - INTERVAL %a MINUTE + ` + sqlSelectUncollectedArtifacts = `SELECT + migration_uuid, + artifacts + FROM %s.schema_migrations + WHERE + migration_status IN ('complete', 'failed') + AND cleanup_timestamp IS NULL + ` + sqlSelectMigration = `SELECT + id, + migration_uuid, + keyspace, + shard, + mysql_schema, + mysql_table, + migration_statement, + strategy, + options, + added_timestamp, + ready_timestamp, + started_timestamp, + liveness_timestamp, + completed_timestamp, + migration_status, + log_path + FROM %s.schema_migrations + WHERE + migration_uuid=%a + ` + sqlSelectReadyMigration = `SELECT + id, + migration_uuid, + keyspace, + shard, + mysql_schema, + mysql_table, + migration_statement, + strategy, + options, + added_timestamp, + ready_timestamp, + started_timestamp, + liveness_timestamp, + completed_timestamp, + migration_status + FROM %s.schema_migrations + WHERE + migration_status='ready' + LIMIT 1 + ` + sqlSelectPTOSCMigrationTriggers = `SELECT + TRIGGER_SCHEMA as trigger_schema, + TRIGGER_NAME as trigger_name + FROM INFORMATION_SCHEMA.TRIGGERS + WHERE + EVENT_OBJECT_SCHEMA=%a + AND EVENT_OBJECT_TABLE=%a + AND ACTION_TIMING='AFTER' + AND LEFT(TRIGGER_NAME, 7)='pt_osc_' + ` + sqlDropTrigger = "DROP TRIGGER IF EXISTS `%a`.`%a`" + sqlShowTablesLike = "SHOW TABLES LIKE '%a'" +) + +const ( + retryMigrationHint = "retry" + cancelMigrationHint = "cancel" +) + +var ( + sqlCreateOnlineDDLUser = []string{ + `CREATE USER IF NOT EXISTS %s IDENTIFIED BY '%s'`, + `ALTER USER %s IDENTIFIED BY '%s'`, + } + sqlGrantOnlineDDLUser = []string{ + `GRANT SUPER, REPLICATION SLAVE ON *.* TO %s`, + `GRANT ALTER, CREATE, DELETE, DROP, INDEX, INSERT, LOCK TABLES, SELECT, TRIGGER, UPDATE ON *.* TO %s`, + } + sqlDropOnlineDDLUser = `DROP USER IF EXISTS %s` +) + +var withDDL = withddl.New([]string{ + fmt.Sprintf(sqlCreateSidecarDB, "_vt"), + fmt.Sprintf(sqlCreateSchemaMigrationsTable, "_vt"), +}) diff --git a/go/vt/vttablet/onlineddl/util.go b/go/vt/vttablet/onlineddl/util.go new file mode 100644 index 00000000000..e901fe7dabd --- /dev/null +++ b/go/vt/vttablet/onlineddl/util.go @@ -0,0 +1,104 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package onlineddl + +import ( + "crypto/rand" + "crypto/sha256" + "encoding/hex" + "fmt" + "io" + "io/ioutil" + "os/exec" + "path/filepath" + "time" + + "vitess.io/vitess/go/vt/log" +) + +const ( + readableTimeFormat = "20060102150405" +) + +// execCmd searches the PATH for a command and runs it, logging the output. +// If input is not nil, pipe it to the command's stdin. +func execCmd(name string, args, env []string, dir string, input io.Reader, output io.Writer) (cmd *exec.Cmd, err error) { + cmdPath, err := exec.LookPath(name) + if err != nil { + return cmd, err + } + log.Infof("execCmd: %v %v %v", name, cmdPath, args) + + cmd = exec.Command(cmdPath, args...) + cmd.Env = env + cmd.Dir = dir + if input != nil { + cmd.Stdin = input + } + if output != nil { + cmd.Stdout = output + cmd.Stderr = output + } + err = cmd.Run() + if err != nil { + err = fmt.Errorf("execCmd failed: %v, %v", name, err) + log.Errorf(err.Error()) + } + log.Infof("execCmd success: %v", name) + return cmd, err +} + +// createTempDir creates a temporary directory and returns its name +func createTempDir(hint string) (dirName string, err error) { + if hint != "" { + return ioutil.TempDir("", fmt.Sprintf("online-ddl-%s-*", hint)) + } + return ioutil.TempDir("", "online-ddl-*") +} + +// createTempScript creates an executable file in given directory and with given text as content. +func createTempScript(dirName, fileName, text string) (fullName string, err error) { + fullName = filepath.Join(dirName, fileName) + bytes := []byte(text) + err = ioutil.WriteFile(fullName, bytes, 0755) + return fullName, err +} + +// RandomHash returns a 64 hex character random string +func RandomHash() string { + size := 64 + rb := make([]byte, size) + _, _ = rand.Read(rb) + + hasher := sha256.New() + hasher.Write(rb) + return hex.EncodeToString(hasher.Sum(nil)) +} + +// ToReadableTimestamp returns a timestamp, in seconds resolution, that is human readable +// (as opposed to unix timestamp which is just a number) +// Example: for Aug 25 2020, 16:04:25 we return "20200825160425" +func ToReadableTimestamp(t time.Time) string { + return t.Format(readableTimeFormat) +} + +// ReadableTimestamp returns a timestamp, in seconds resolution, that is human readable +// (as opposed to unix timestamp which is just a number), and which corresponds to the time now. +// Example: for Aug 25 2020, 16:04:25 we return "20200825160425" +func ReadableTimestamp() string { + return ToReadableTimestamp(time.Now()) +} diff --git a/go/vt/vttablet/onlineddl/util_test.go b/go/vt/vttablet/onlineddl/util_test.go new file mode 100644 index 00000000000..707e321c6f5 --- /dev/null +++ b/go/vt/vttablet/onlineddl/util_test.go @@ -0,0 +1,41 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package onlineddl + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestRandomHash(t *testing.T) { + h1 := RandomHash() + h2 := RandomHash() + + assert.Equal(t, len(h1), 64) + assert.Equal(t, len(h2), 64) + assert.NotEqual(t, h1, h2) +} + +func TestToReadableTimestamp(t *testing.T) { + ti, err := time.Parse(time.UnixDate, "Wed Feb 25 11:06:39 PST 2015") + assert.NoError(t, err) + + readableTimestamp := ToReadableTimestamp(ti) + assert.Equal(t, readableTimestamp, "20150225110639") +} diff --git a/go/vt/vttablet/tabletmanager/rpc_agent.go b/go/vt/vttablet/tabletmanager/rpc_agent.go index 6e50d7510b4..e8ba5cd0e90 100644 --- a/go/vt/vttablet/tabletmanager/rpc_agent.go +++ b/go/vt/vttablet/tabletmanager/rpc_agent.go @@ -114,6 +114,9 @@ type RPCTM interface { WaitForPosition(ctx context.Context, pos string) error + // VExec generic API + VExec(ctx context.Context, query, workflow, keyspace string) (*querypb.QueryResult, error) + // VReplication API VReplicationExec(ctx context.Context, query string) (*querypb.QueryResult, error) VReplicationWaitForPos(ctx context.Context, id int, pos string) error diff --git a/go/vt/vttablet/tabletmanager/rpc_vexec.go b/go/vt/vttablet/tabletmanager/rpc_vexec.go new file mode 100644 index 00000000000..9a9aa48b001 --- /dev/null +++ b/go/vt/vttablet/tabletmanager/rpc_vexec.go @@ -0,0 +1,41 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tabletmanager + +import ( + "fmt" + + querypb "vitess.io/vitess/go/vt/proto/query" + "vitess.io/vitess/go/vt/vttablet/onlineddl" + "vitess.io/vitess/go/vt/vttablet/vexec" + + "golang.org/x/net/context" +) + +// VExec executes a generic VExec command. +func (tm *TabletManager) VExec(ctx context.Context, query, workflow, keyspace string) (*querypb.QueryResult, error) { + vx := vexec.NewTabletVExec(workflow, keyspace) + if err := vx.AnalyzeQuery(ctx, query); err != nil { + return nil, err + } + switch vx.TableName { + case fmt.Sprintf("%s.%s", vexec.TableQualifier, onlineddl.SchemaMigrationsTableName): + return tm.QueryServiceControl.OnlineDDLExecutor().VExec(ctx, vx) + default: + return nil, fmt.Errorf("table not supported by vexec: %v", vx.TableName) + } +} diff --git a/go/vt/vttablet/tabletserver/controller.go b/go/vt/vttablet/tabletserver/controller.go index 0347924288a..9a4e49e5393 100644 --- a/go/vt/vttablet/tabletserver/controller.go +++ b/go/vt/vttablet/tabletserver/controller.go @@ -22,6 +22,7 @@ import ( "vitess.io/vitess/go/vt/dbconfigs" "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vttablet/onlineddl" "vitess.io/vitess/go/vt/vttablet/queryservice" "vitess.io/vitess/go/vt/vttablet/tabletserver/rules" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -48,7 +49,7 @@ type Controller interface { Stats() *tabletenv.Stats // InitDBConfig sets up the db config vars. - InitDBConfig(querypb.Target, *dbconfigs.DBConfigs, mysqlctl.MysqlDaemon) error + InitDBConfig(target querypb.Target, dbConfigs *dbconfigs.DBConfigs, mysqlDaemon mysqlctl.MysqlDaemon) error // SetServingType transitions the query service to the required serving type. // Returns true if the state of QueryService or the tablet type changed. @@ -81,6 +82,9 @@ type Controller interface { // QueryService returns the QueryService object used by this Controller QueryService() queryservice.QueryService + // OnlineDDLExecutor the online DDL executor used by this Controller + OnlineDDLExecutor() *onlineddl.Executor + // SchemaEngine returns the SchemaEngine object used by this Controller SchemaEngine() *schema.Engine diff --git a/go/vt/vttablet/tabletserver/repltracker/repltracker.go b/go/vt/vttablet/tabletserver/repltracker/repltracker.go index 99e0b7444b4..5dca2c59356 100644 --- a/go/vt/vttablet/tabletserver/repltracker/repltracker.go +++ b/go/vt/vttablet/tabletserver/repltracker/repltracker.go @@ -50,7 +50,8 @@ var ( // ReplTracker tracks replication lag. type ReplTracker struct { - mode string + mode string + forceHeartbeat bool mu sync.Mutex isMaster bool @@ -63,10 +64,11 @@ type ReplTracker struct { // NewReplTracker creates a new ReplTracker. func NewReplTracker(env tabletenv.Env, alias topodatapb.TabletAlias) *ReplTracker { return &ReplTracker{ - mode: env.Config().ReplicationTracker.Mode, - hw: newHeartbeatWriter(env, alias), - hr: newHeartbeatReader(env), - poller: &poller{}, + mode: env.Config().ReplicationTracker.Mode, + forceHeartbeat: env.Config().EnableLagThrottler, + hw: newHeartbeatWriter(env, alias), + hr: newHeartbeatReader(env), + poller: &poller{}, } } @@ -88,6 +90,9 @@ func (rt *ReplTracker) MakeMaster() { rt.hr.Close() rt.hw.Open() } + if rt.forceHeartbeat { + rt.hw.Open() + } } // MakeNonMaster must be called if the tablet type becomes non-MASTER. @@ -105,6 +110,9 @@ func (rt *ReplTracker) MakeNonMaster() { // Run the status once to pre-initialize values. rt.poller.Status() } + if rt.forceHeartbeat { + rt.hw.Close() + } } // Close closes ReplTracker. diff --git a/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go b/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go index 250fd89b2fa..632859ab33e 100644 --- a/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go +++ b/go/vt/vttablet/tabletserver/repltracker/repltracker_test.go @@ -82,7 +82,7 @@ func TestReplTracker(t *testing.T) { rt.InitDBConfig(target, mysqld) assert.Equal(t, tabletenv.Polling, rt.mode) assert.Equal(t, mysqld, rt.poller.mysqld) - assert.True(t, rt.hw.enabled) + assert.False(t, rt.hw.enabled) assert.False(t, rt.hr.enabled) rt.MakeNonMaster() diff --git a/go/vt/vttablet/tabletserver/repltracker/writer.go b/go/vt/vttablet/tabletserver/repltracker/writer.go index a7b8bf18637..828e0079d9a 100644 --- a/go/vt/vttablet/tabletserver/repltracker/writer.go +++ b/go/vt/vttablet/tabletserver/repltracker/writer.go @@ -73,6 +73,11 @@ type heartbeatWriter struct { // newHeartbeatWriter creates a new heartbeatWriter. func newHeartbeatWriter(env tabletenv.Env, alias topodatapb.TabletAlias) *heartbeatWriter { config := env.Config() + + // config.EnableLagThrottler is a feature flag for the throttler; if throttler runs, then heartbeat must also run + if config.ReplicationTracker.Mode != tabletenv.Heartbeat && !config.EnableLagThrottler { + return &heartbeatWriter{} + } heartbeatInterval := config.ReplicationTracker.HeartbeatIntervalSeconds.Get() return &heartbeatWriter{ env: env, @@ -182,6 +187,9 @@ func (w *heartbeatWriter) recordError(err error) { // enableWrites actives or deactives heartbeat writes func (w *heartbeatWriter) enableWrites(enable bool) { + if w.ticks == nil { + return + } if enable { w.ticks.Start(w.writeHeartbeat) } else { diff --git a/go/vt/vttablet/tabletserver/state_manager.go b/go/vt/vttablet/tabletserver/state_manager.go index 354a39905f3..953107e137a 100644 --- a/go/vt/vttablet/tabletserver/state_manager.go +++ b/go/vt/vttablet/tabletserver/state_manager.go @@ -105,6 +105,7 @@ type stateManager struct { txThrottler txThrottler te txEngine messager subComponent + ddle onlineDDLExecutor throttler lagThrottler // hcticks starts on initialiazation and runs forever. @@ -157,6 +158,11 @@ type ( Close() } + onlineDDLExecutor interface { + Open() error + Close() + } + lagThrottler interface { Open() error Close() @@ -410,6 +416,7 @@ func (sm *stateManager) serveMaster() error { } sm.messager.Open() sm.throttler.Open() + sm.ddle.Open() sm.setState(topodatapb.TabletType_MASTER, StateServing) return nil } @@ -429,6 +436,7 @@ func (sm *stateManager) unserveMaster() error { } func (sm *stateManager) serveNonMaster(wantTabletType topodatapb.TabletType) error { + sm.ddle.Close() sm.throttler.Close() sm.messager.Close() sm.tracker.Close() @@ -477,6 +485,7 @@ func (sm *stateManager) connect(tabletType topodatapb.TabletType) error { } func (sm *stateManager) unserveCommon() { + sm.ddle.Close() sm.throttler.Close() sm.messager.Close() sm.te.Close() diff --git a/go/vt/vttablet/tabletserver/state_manager_test.go b/go/vt/vttablet/tabletserver/state_manager_test.go index a8f55b50076..610bc148434 100644 --- a/go/vt/vttablet/tabletserver/state_manager_test.go +++ b/go/vt/vttablet/tabletserver/state_manager_test.go @@ -81,6 +81,7 @@ func TestStateManagerServeMaster(t *testing.T) { verifySubcomponent(t, 8, sm.te, testStateMaster) verifySubcomponent(t, 9, sm.messager, testStateOpen) verifySubcomponent(t, 10, sm.throttler, testStateOpen) + verifySubcomponent(t, 11, sm.ddle, testStateOpen) assert.False(t, sm.se.(*testSchemaEngine).nonMaster) assert.True(t, sm.se.(*testSchemaEngine).ensureCalled) @@ -96,18 +97,19 @@ func TestStateManagerServeNonMaster(t *testing.T) { err := sm.SetServingType(topodatapb.TabletType_REPLICA, testNow, StateServing, "") require.NoError(t, err) - verifySubcomponent(t, 1, sm.throttler, testStateClosed) - verifySubcomponent(t, 2, sm.messager, testStateClosed) - verifySubcomponent(t, 3, sm.tracker, testStateClosed) + verifySubcomponent(t, 1, sm.ddle, testStateClosed) + verifySubcomponent(t, 2, sm.throttler, testStateClosed) + verifySubcomponent(t, 3, sm.messager, testStateClosed) + verifySubcomponent(t, 4, sm.tracker, testStateClosed) assert.True(t, sm.se.(*testSchemaEngine).nonMaster) - verifySubcomponent(t, 4, sm.se, testStateOpen) - verifySubcomponent(t, 5, sm.vstreamer, testStateOpen) - verifySubcomponent(t, 6, sm.qe, testStateOpen) - verifySubcomponent(t, 7, sm.txThrottler, testStateOpen) - verifySubcomponent(t, 8, sm.te, testStateNonMaster) - verifySubcomponent(t, 9, sm.rt, testStateNonMaster) - verifySubcomponent(t, 10, sm.watcher, testStateOpen) + verifySubcomponent(t, 5, sm.se, testStateOpen) + verifySubcomponent(t, 6, sm.vstreamer, testStateOpen) + verifySubcomponent(t, 7, sm.qe, testStateOpen) + verifySubcomponent(t, 8, sm.txThrottler, testStateOpen) + verifySubcomponent(t, 9, sm.te, testStateNonMaster) + verifySubcomponent(t, 10, sm.rt, testStateNonMaster) + verifySubcomponent(t, 11, sm.watcher, testStateOpen) assert.Equal(t, topodatapb.TabletType_REPLICA, sm.target.TabletType) assert.Equal(t, StateServing, sm.state) @@ -119,19 +121,20 @@ func TestStateManagerUnserveMaster(t *testing.T) { err := sm.SetServingType(topodatapb.TabletType_MASTER, testNow, StateNotServing, "") require.NoError(t, err) - verifySubcomponent(t, 1, sm.throttler, testStateClosed) - verifySubcomponent(t, 2, sm.messager, testStateClosed) - verifySubcomponent(t, 3, sm.te, testStateClosed) + verifySubcomponent(t, 1, sm.ddle, testStateClosed) + verifySubcomponent(t, 2, sm.throttler, testStateClosed) + verifySubcomponent(t, 3, sm.messager, testStateClosed) + verifySubcomponent(t, 4, sm.te, testStateClosed) assert.True(t, sm.qe.(*testQueryEngine).stopServing) - verifySubcomponent(t, 4, sm.tracker, testStateClosed) - verifySubcomponent(t, 5, sm.watcher, testStateClosed) - verifySubcomponent(t, 6, sm.se, testStateOpen) - verifySubcomponent(t, 7, sm.vstreamer, testStateOpen) - verifySubcomponent(t, 8, sm.qe, testStateOpen) - verifySubcomponent(t, 9, sm.txThrottler, testStateOpen) + verifySubcomponent(t, 5, sm.tracker, testStateClosed) + verifySubcomponent(t, 6, sm.watcher, testStateClosed) + verifySubcomponent(t, 7, sm.se, testStateOpen) + verifySubcomponent(t, 8, sm.vstreamer, testStateOpen) + verifySubcomponent(t, 9, sm.qe, testStateOpen) + verifySubcomponent(t, 10, sm.txThrottler, testStateOpen) - verifySubcomponent(t, 10, sm.rt, testStateMaster) + verifySubcomponent(t, 11, sm.rt, testStateMaster) assert.Equal(t, topodatapb.TabletType_MASTER, sm.target.TabletType) assert.Equal(t, StateNotServing, sm.state) @@ -143,21 +146,22 @@ func TestStateManagerUnserveNonmaster(t *testing.T) { err := sm.SetServingType(topodatapb.TabletType_RDONLY, testNow, StateNotServing, "") require.NoError(t, err) - verifySubcomponent(t, 1, sm.throttler, testStateClosed) - verifySubcomponent(t, 2, sm.messager, testStateClosed) - verifySubcomponent(t, 3, sm.te, testStateClosed) + verifySubcomponent(t, 1, sm.ddle, testStateClosed) + verifySubcomponent(t, 2, sm.throttler, testStateClosed) + verifySubcomponent(t, 3, sm.messager, testStateClosed) + verifySubcomponent(t, 4, sm.te, testStateClosed) assert.True(t, sm.qe.(*testQueryEngine).stopServing) - verifySubcomponent(t, 4, sm.tracker, testStateClosed) + verifySubcomponent(t, 5, sm.tracker, testStateClosed) assert.True(t, sm.se.(*testSchemaEngine).nonMaster) - verifySubcomponent(t, 5, sm.se, testStateOpen) - verifySubcomponent(t, 6, sm.vstreamer, testStateOpen) - verifySubcomponent(t, 7, sm.qe, testStateOpen) - verifySubcomponent(t, 8, sm.txThrottler, testStateOpen) + verifySubcomponent(t, 6, sm.se, testStateOpen) + verifySubcomponent(t, 7, sm.vstreamer, testStateOpen) + verifySubcomponent(t, 8, sm.qe, testStateOpen) + verifySubcomponent(t, 9, sm.txThrottler, testStateOpen) - verifySubcomponent(t, 9, sm.rt, testStateNonMaster) - verifySubcomponent(t, 10, sm.watcher, testStateOpen) + verifySubcomponent(t, 10, sm.rt, testStateNonMaster) + verifySubcomponent(t, 11, sm.watcher, testStateOpen) assert.Equal(t, topodatapb.TabletType_RDONLY, sm.target.TabletType) assert.Equal(t, StateNotServing, sm.state) @@ -169,18 +173,19 @@ func TestStateManagerClose(t *testing.T) { err := sm.SetServingType(topodatapb.TabletType_RDONLY, testNow, StateNotConnected, "") require.NoError(t, err) - verifySubcomponent(t, 1, sm.throttler, testStateClosed) - verifySubcomponent(t, 2, sm.messager, testStateClosed) - verifySubcomponent(t, 3, sm.te, testStateClosed) + verifySubcomponent(t, 1, sm.ddle, testStateClosed) + verifySubcomponent(t, 2, sm.throttler, testStateClosed) + verifySubcomponent(t, 3, sm.messager, testStateClosed) + verifySubcomponent(t, 4, sm.te, testStateClosed) assert.True(t, sm.qe.(*testQueryEngine).stopServing) - verifySubcomponent(t, 4, sm.tracker, testStateClosed) + verifySubcomponent(t, 5, sm.tracker, testStateClosed) - verifySubcomponent(t, 5, sm.txThrottler, testStateClosed) - verifySubcomponent(t, 6, sm.qe, testStateClosed) - verifySubcomponent(t, 7, sm.watcher, testStateClosed) - verifySubcomponent(t, 8, sm.vstreamer, testStateClosed) - verifySubcomponent(t, 9, sm.rt, testStateClosed) - verifySubcomponent(t, 10, sm.se, testStateClosed) + verifySubcomponent(t, 6, sm.txThrottler, testStateClosed) + verifySubcomponent(t, 7, sm.qe, testStateClosed) + verifySubcomponent(t, 8, sm.watcher, testStateClosed) + verifySubcomponent(t, 9, sm.vstreamer, testStateClosed) + verifySubcomponent(t, 10, sm.rt, testStateClosed) + verifySubcomponent(t, 11, sm.se, testStateClosed) assert.Equal(t, topodatapb.TabletType_RDONLY, sm.target.TabletType) assert.Equal(t, StateNotConnected, sm.state) @@ -282,18 +287,19 @@ func TestStateManagerSetServingTypeNoChange(t *testing.T) { err = sm.SetServingType(topodatapb.TabletType_REPLICA, testNow, StateServing, "") require.NoError(t, err) - verifySubcomponent(t, 1, sm.throttler, testStateClosed) - verifySubcomponent(t, 2, sm.messager, testStateClosed) - verifySubcomponent(t, 3, sm.tracker, testStateClosed) + verifySubcomponent(t, 1, sm.ddle, testStateClosed) + verifySubcomponent(t, 2, sm.throttler, testStateClosed) + verifySubcomponent(t, 3, sm.messager, testStateClosed) + verifySubcomponent(t, 4, sm.tracker, testStateClosed) assert.True(t, sm.se.(*testSchemaEngine).nonMaster) - verifySubcomponent(t, 4, sm.se, testStateOpen) - verifySubcomponent(t, 5, sm.vstreamer, testStateOpen) - verifySubcomponent(t, 6, sm.qe, testStateOpen) - verifySubcomponent(t, 7, sm.txThrottler, testStateOpen) - verifySubcomponent(t, 8, sm.te, testStateNonMaster) - verifySubcomponent(t, 9, sm.rt, testStateNonMaster) - verifySubcomponent(t, 10, sm.watcher, testStateOpen) + verifySubcomponent(t, 5, sm.se, testStateOpen) + verifySubcomponent(t, 6, sm.vstreamer, testStateOpen) + verifySubcomponent(t, 7, sm.qe, testStateOpen) + verifySubcomponent(t, 8, sm.txThrottler, testStateOpen) + verifySubcomponent(t, 9, sm.te, testStateNonMaster) + verifySubcomponent(t, 10, sm.rt, testStateNonMaster) + verifySubcomponent(t, 11, sm.watcher, testStateOpen) assert.Equal(t, topodatapb.TabletType_REPLICA, sm.target.TabletType) assert.Equal(t, StateServing, sm.state) @@ -596,6 +602,7 @@ func newTestStateManager(t *testing.T) *stateManager { txThrottler: &testTxThrottler{}, te: &testTxEngine{}, messager: &testSubcomponent{}, + ddle: &testOnlineDDLExecutor{}, throttler: &testLagThrottler{}, } sm.Init(env, querypb.Target{}) @@ -779,6 +786,21 @@ func (te *testTxThrottler) Close() { te.state = testStateClosed } +type testOnlineDDLExecutor struct { + testOrderState +} + +func (te *testOnlineDDLExecutor) Open() error { + te.order = order.Add(1) + te.state = testStateOpen + return nil +} + +func (te *testOnlineDDLExecutor) Close() { + te.order = order.Add(1) + te.state = testStateClosed +} + type testLagThrottler struct { testOrderState } diff --git a/go/vt/vttablet/tabletserver/tabletenv/config.go b/go/vt/vttablet/tabletserver/tabletenv/config.go index f555e807bde..122166bc618 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/config.go +++ b/go/vt/vttablet/tabletserver/tabletenv/config.go @@ -142,6 +142,7 @@ func init() { flag.BoolVar(&enableHeartbeat, "heartbeat_enable", false, "If true, vttablet records (if master) or checks (if replica) the current time of a replication heartbeat in the table _vt.heartbeat. The result is used to inform the serving state of the vttablet via healthchecks.") flag.DurationVar(&heartbeatInterval, "heartbeat_interval", 1*time.Second, "How frequently to read and write replication heartbeat.") + flag.BoolVar(¤tConfig.EnableLagThrottler, "enable-lag-throttler", defaultConfig.EnableLagThrottler, "If true, vttablet will run a throttler service, and will implicitly enable heartbeats") flag.BoolVar(¤tConfig.EnforceStrictTransTables, "enforce_strict_trans_tables", defaultConfig.EnforceStrictTransTables, "If true, vttablet requires MySQL to run with STRICT_TRANS_TABLES or STRICT_ALL_TABLES on. It is recommended to not turn this flag off. Otherwise MySQL may alter your supplied values before saving them to the database.") flag.BoolVar(&enableConsolidator, "enable-consolidator", true, "This option enables the query consolidator.") @@ -261,6 +262,8 @@ type TabletConfig struct { TxThrottlerConfig string `json:"-"` TxThrottlerHealthCheckCells []string `json:"-"` + EnableLagThrottler bool `json:"-"` + TransactionLimitConfig `json:"-"` EnforceStrictTransTables bool `json:"-"` @@ -452,6 +455,8 @@ var defaultConfig = TabletConfig{ TxThrottlerConfig: defaultTxThrottlerConfig(), TxThrottlerHealthCheckCells: []string{}, + EnableLagThrottler: false, // Feature flag; to switch to 'true' at some stage in the future + TransactionLimitConfig: defaultTransactionLimitConfig(), EnforceStrictTransTables: true, diff --git a/go/vt/vttablet/tabletserver/tabletserver.go b/go/vt/vttablet/tabletserver/tabletserver.go index 8d3649a2de9..24156b8e6cf 100644 --- a/go/vt/vttablet/tabletserver/tabletserver.go +++ b/go/vt/vttablet/tabletserver/tabletserver.go @@ -52,6 +52,7 @@ import ( "vitess.io/vitess/go/vt/tableacl" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/onlineddl" "vitess.io/vitess/go/vt/vttablet/queryservice" "vitess.io/vitess/go/vt/vttablet/tabletserver/messager" "vitess.io/vitess/go/vt/vttablet/tabletserver/planbuilder" @@ -107,7 +108,8 @@ type TabletServer struct { lagThrottler *throttle.Throttler // sm manages state transitions. - sm *stateManager + sm *stateManager + onlineDDLExecutor *onlineddl.Executor // alias is used for identifying this tabletserver in healthcheck responses. alias topodatapb.TabletAlias @@ -157,14 +159,15 @@ func NewTabletServer(name string, config *tabletenv.TabletConfig, topoServer *to tsv.txThrottler = txthrottler.NewTxThrottler(tsv.config, topoServer) tsv.te = NewTxEngine(tsv) tsv.messager = messager.NewEngine(tsv, tsv.se, tsv.vstreamer) - tsv.lagThrottler = throttle.NewThrottler(tsv, topoServer, - func() topodatapb.TabletType { - if tsv.sm == nil { - return topodatapb.TabletType_UNKNOWN - } - return tsv.sm.Target().TabletType - }, - ) + + tabletTypeFunc := func() topodatapb.TabletType { + if tsv.sm == nil { + return topodatapb.TabletType_UNKNOWN + } + return tsv.sm.Target().TabletType + } + tsv.onlineDDLExecutor = onlineddl.NewExecutor(tsv, topoServer, tabletTypeFunc) + tsv.lagThrottler = throttle.NewThrottler(tsv, topoServer, tabletTypeFunc) tsv.sm = &stateManager{ hs: tsv.hs, @@ -177,6 +180,7 @@ func NewTabletServer(name string, config *tabletenv.TabletConfig, topoServer *to txThrottler: tsv.txThrottler, te: tsv.te, messager: tsv.messager, + ddle: tsv.onlineDDLExecutor, throttler: tsv.lagThrottler, } @@ -195,6 +199,7 @@ func NewTabletServer(name string, config *tabletenv.TabletConfig, topoServer *to tsv.registerQueryzHandler() tsv.registerStreamQueryzHandlers() tsv.registerTwopczHandler() + tsv.registerMigrationStatusHandler() tsv.registerThrottlerHandlers() return tsv @@ -215,6 +220,7 @@ func (tsv *TabletServer) InitDBConfig(target querypb.Target, dbcfgs *dbconfigs.D tsv.txThrottler.InitDBConfig(target) tsv.vstreamer.InitDBConfig(target.Keyspace) tsv.hs.InitDBConfig(target) + tsv.onlineDDLExecutor.InitDBConfig(target.Keyspace, target.Shard, dbcfgs.DBName) tsv.lagThrottler.InitDBConfig(target.Keyspace, target.Shard) return nil } @@ -377,6 +383,11 @@ func (tsv *TabletServer) QueryService() queryservice.QueryService { return tsv } +// OnlineDDLExecutor returns the onlineddl.Executor part of TabletServer. +func (tsv *TabletServer) OnlineDDLExecutor() *onlineddl.Executor { + return tsv.onlineDDLExecutor +} + // LagThrottler returns the throttle.Throttler part of TabletServer. func (tsv *TabletServer) LagThrottler() *throttle.Throttler { return tsv.lagThrottler @@ -1475,6 +1486,17 @@ func (tsv *TabletServer) registerTwopczHandler() { }) } +func (tsv *TabletServer) registerMigrationStatusHandler() { + tsv.exporter.HandleFunc("/schema-migration/report-status", func(w http.ResponseWriter, r *http.Request) { + ctx := tabletenv.LocalContext() + if err := tsv.onlineDDLExecutor.OnSchemaMigrationStatus(ctx, r.URL.Query().Get("uuid"), r.URL.Query().Get("status"), r.URL.Query().Get("dryrun")); err != nil { + http.Error(w, fmt.Sprintf("not ok: %v", err), http.StatusInternalServerError) + return + } + w.Write([]byte("ok")) + }) +} + // registerThrottlerCheckHandler registers a throttler "check" request func (tsv *TabletServer) registerThrottlerCheckHandler() { tsv.exporter.HandleFunc("/throttler/check", func(w http.ResponseWriter, r *http.Request) { diff --git a/go/vt/vttablet/tabletserver/throttle/check_result.go b/go/vt/vttablet/tabletserver/throttle/check_result.go index f17b315ee86..9981109694c 100644 --- a/go/vt/vttablet/tabletserver/throttle/check_result.go +++ b/go/vt/vttablet/tabletserver/throttle/check_result.go @@ -42,3 +42,5 @@ func NewErrorCheckResult(statusCode int, err error) *CheckResult { // NoSuchMetricCheckResult is a result returns when a metric is unknown var NoSuchMetricCheckResult = NewErrorCheckResult(http.StatusNotFound, base.ErrNoSuchMetric) + +var okMetricCheckResult = NewCheckResult(http.StatusOK, 0, 0, nil) diff --git a/go/vt/vttablet/tabletserver/throttle/throttler.go b/go/vt/vttablet/tabletserver/throttle/throttler.go index 2230c0516eb..e7999da800f 100644 --- a/go/vt/vttablet/tabletserver/throttle/throttler.go +++ b/go/vt/vttablet/tabletserver/throttle/throttler.go @@ -186,7 +186,9 @@ func (throttler *Throttler) initThrottleTabletTypes() { func (throttler *Throttler) InitDBConfig(keyspace, shard string) { throttler.keyspace = keyspace throttler.shard = shard - go throttler.Operate(context.Background()) + if throttler.env.Config().EnableLagThrottler { + go throttler.Operate(context.Background()) + } } // initThrottler initializes config @@ -692,6 +694,9 @@ func (throttler *Throttler) AppRequestMetricResult(ctx context.Context, appName // Check is the main serving function of the throttler, and returns a check result for this cluster's lag func (throttler *Throttler) Check(ctx context.Context, appName string, remoteAddr string, flags *CheckFlags) (checkResult *CheckResult) { + if !throttler.env.Config().EnableLagThrottler { + return okMetricCheckResult + } return throttler.check.Check(ctx, appName, "mysql", localStoreName, remoteAddr, flags) } diff --git a/go/vt/vttablet/tabletservermock/controller.go b/go/vt/vttablet/tabletservermock/controller.go index 0c06672bdc3..277238ba727 100644 --- a/go/vt/vttablet/tabletservermock/controller.go +++ b/go/vt/vttablet/tabletservermock/controller.go @@ -28,6 +28,7 @@ import ( "vitess.io/vitess/go/vt/mysqlctl" "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/vt/topo" + "vitess.io/vitess/go/vt/vttablet/onlineddl" "vitess.io/vitess/go/vt/vttablet/queryservice" "vitess.io/vitess/go/vt/vttablet/tabletserver/rules" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" @@ -174,6 +175,11 @@ func (tqsc *Controller) ReloadSchema(ctx context.Context) error { return nil } +// OnlineDDLExecutor is part of the tabletserver.Controller interface +func (tqsc *Controller) OnlineDDLExecutor() *onlineddl.Executor { + return nil +} + //ClearQueryPlanCache is part of the tabletserver.Controller interface func (tqsc *Controller) ClearQueryPlanCache() { } diff --git a/go/vt/vttablet/tmclient/rpc_client_api.go b/go/vt/vttablet/tmclient/rpc_client_api.go index 85206bf0b66..dc1f220958c 100644 --- a/go/vt/vttablet/tmclient/rpc_client_api.go +++ b/go/vt/vttablet/tmclient/rpc_client_api.go @@ -156,6 +156,9 @@ type TabletManagerClient interface { // WaitForPosition waits for the position to be reached WaitForPosition(ctx context.Context, tablet *topodatapb.Tablet, pos string) error + // VExec executes a generic VExec command + VExec(ctx context.Context, tablet *topodatapb.Tablet, query, workflow, keyspace string) (*querypb.QueryResult, error) + // VReplicationExec executes a VReplication command VReplicationExec(ctx context.Context, tablet *topodatapb.Tablet, query string) (*querypb.QueryResult, error) VReplicationWaitForPos(ctx context.Context, tablet *topodatapb.Tablet, id int, pos string) error diff --git a/go/vt/vttablet/tmrpctest/test_tm_rpc.go b/go/vt/vttablet/tmrpctest/test_tm_rpc.go index babb5ec25ac..40081f2346b 100644 --- a/go/vt/vttablet/tmrpctest/test_tm_rpc.go +++ b/go/vt/vttablet/tmrpctest/test_tm_rpc.go @@ -960,6 +960,14 @@ func tmRPCTestGetReplicasPanic(ctx context.Context, t *testing.T, client tmclien expectHandleRPCPanic(t, "GetReplicas", false /*verbose*/, err) } +func (fra *fakeRPCTM) VExec(ctx context.Context, query, workflow, keyspace string) (*querypb.QueryResult, error) { + if fra.panics { + panic(fmt.Errorf("test-triggered panic")) + } + compare(fra.t, "VExec query", query, "query") + return testExecuteFetchResult, nil +} + var testVRQuery = "query" func (fra *fakeRPCTM) VReplicationExec(ctx context.Context, query string) (*querypb.QueryResult, error) { diff --git a/go/vt/vttablet/vexec/vexec.go b/go/vt/vttablet/vexec/vexec.go new file mode 100644 index 00000000000..626c801edc7 --- /dev/null +++ b/go/vt/vttablet/vexec/vexec.go @@ -0,0 +1,201 @@ +package vexec + +import ( + "context" + "fmt" + + "vitess.io/vitess/go/vt/sqlparser" +) + +const ( + // TableQualifier is the standard schema used by VExec commands + TableQualifier = "_vt" +) + +// ValColumns map column name to Literal, for col=Val expressions in a WHERE clause +type ValColumns map[string](*sqlparser.Literal) + +// TabletVExec is a utility structure, created when a VExec command is intercepted on the tablet. +// This structure will parse and analyze the query, and make available some useful data. +// VExec interceptors receive an instance of this struct so they can run more analysis/checks +// on the given query, and potentially modify it. +type TabletVExec struct { + Workflow string + Keyspace string + Query string + Stmt sqlparser.Statement + TableName string + WhereCols ValColumns + UpdateCols ValColumns + InsertCols ValColumns +} + +// NewTabletVExec creates a new instance of TabletVExec +func NewTabletVExec(workflow, keyspace string) *TabletVExec { + return &TabletVExec{ + Workflow: workflow, + Keyspace: keyspace, + } +} + +// ToStringVal converts a string to a string -typed Literal +func (e *TabletVExec) ToStringVal(val string) *sqlparser.Literal { + return &sqlparser.Literal{ + Type: sqlparser.StrVal, + Val: []byte(val), + } +} + +// ColumnStringVal returns a string value from a given column, or error if the column is not found +func (e *TabletVExec) ColumnStringVal(columns ValColumns, colName string) (string, error) { + val, ok := columns[colName] + if !ok { + return "", fmt.Errorf("Could not find value for column %s", colName) + } + return string(val.Val), nil +} + +// SetColumnStringVal modifies a column value into a given string +func (e *TabletVExec) SetColumnStringVal(columns ValColumns, colName string, val string) { + columns[colName] = e.ToStringVal(val) +} + +// analyzeWhereColumns identifies column names in a WHERE clause that have a comparison expression +// e.g. will return `keyspace` in a "WHERE keyspace='abc'" +// will not return `keyspace` in a "WHERE keyspace LIKE '%'" +func (e *TabletVExec) analyzeWhereEqualsColumns(where *sqlparser.Where) ValColumns { + cols := ValColumns{} + if where == nil { + return cols + } + exprs := sqlparser.SplitAndExpression(nil, where.Expr) + for _, expr := range exprs { + switch expr := expr.(type) { + case *sqlparser.ComparisonExpr: + if expr.Operator != sqlparser.EqualOp { + continue + } + qualifiedName, ok := expr.Left.(*sqlparser.ColName) + if !ok { + continue + } + if val, ok := expr.Right.(*sqlparser.Literal); ok { + cols[qualifiedName.Name.String()] = val + } + } + } + return cols +} + +// analyzeUpdateColumns analyses the columns modified by an UPDATE statement. +// it returns the columns that are updated with a literal +// e.g. in this statement: UPDATE tbl SET name='foo', val=3, status=other_column+2 +// the function returns name: 'foo' and val: 3, but does not return `status` column +func (e *TabletVExec) analyzeUpdateColumns(update *sqlparser.Update) ValColumns { + cols := ValColumns{} + for _, col := range update.Exprs { + if val, ok := col.Expr.(*sqlparser.Literal); ok { + cols[col.Name.Name.Lowered()] = val + } + } + return cols +} + +// analyzeInsertColumns analyses the columns and values given in an INSERT statement +func (e *TabletVExec) analyzeInsertColumns(insert *sqlparser.Insert) ValColumns { + cols := ValColumns{} + + rows, ok := insert.Rows.(sqlparser.Values) + if !ok { + return cols + } + + if len(rows) != 1 { + return cols + } + for i, col := range insert.Columns { + expr := rows[0][i] + if val, ok := expr.(*sqlparser.Literal); ok { + cols[col.Lowered()] = val + } + } + return cols +} + +// ReplaceInsertColumnVal manipulated the existing INSERT statement to replace a column value +// into a given value +func (e *TabletVExec) ReplaceInsertColumnVal(colName string, val *sqlparser.Literal) error { + insert, ok := e.Stmt.(*sqlparser.Insert) + if !ok { + return fmt.Errorf("Not an INSERT statement") + } + rows, ok := insert.Rows.(sqlparser.Values) + if !ok { + return fmt.Errorf("Not a Values type INSERT") + } + if len(rows) != 1 { + return fmt.Errorf("Not a single row INSERT") + } + for i, col := range insert.Columns { + if col.Lowered() == colName { + rows[0][i] = val + e.InsertCols[colName] = val + e.Query = sqlparser.String(e.Stmt) + return nil + } + } + return fmt.Errorf("INSERT column not found: %s", colName) +} + +// analyzeStatement analyzes a given statement and produces the following ingredients, useful for +// VExec interceptors: +// - table name +// - column names with values, for col=VAL in a WHERE expression +// e.g. in "UPDATE my_table SET ... WHERE keyspace='test' AND shard='-80' AND status > 2", the +// ValColumns are "keyspace" and "shard" with matching values. `status` is a range operator therefore +// not included.package vexec +// Equals operator is of special importance because it is known to filter results. An interceptor may +// require, for example, that a `DELETE` statement includes a WHERE with a UNIQUE KEY column with Equals operator +// to ensure we're not doing anything too risky. +func (e *TabletVExec) analyzeStatement() error { + switch stmt := e.Stmt.(type) { + case *sqlparser.Update: + e.TableName = sqlparser.String(stmt.TableExprs) + e.WhereCols = e.analyzeWhereEqualsColumns(stmt.Where) + e.UpdateCols = e.analyzeUpdateColumns(stmt) + case *sqlparser.Delete: + e.TableName = sqlparser.String(stmt.TableExprs) + e.WhereCols = e.analyzeWhereEqualsColumns(stmt.Where) + case *sqlparser.Insert: + e.TableName = sqlparser.String(stmt.Table) + e.InsertCols = e.analyzeInsertColumns(stmt) + case *sqlparser.Select: + e.TableName = sqlparser.String(stmt.From) + e.WhereCols = e.analyzeWhereEqualsColumns(stmt.Where) + default: + return fmt.Errorf("query not supported by vexec: %+v", sqlparser.String(stmt)) + } + return nil +} + +// AnalyzeQuery analyzes a given statement and produces the following ingredients, useful for +// VExec interceptors: +// - parsed statement +// - table name +// - column names with values, for col=VAL in a WHERE expression +// e.g. in "UPDATE my_table SET ... WHERE keyspace='test' AND shard='-80' AND status > 2", the +// ValColumns are "keyspace" and "shard" with matching values. `status` is a range operator therefore +// not included.package vexec +// Equals operator is of special importance because it is known to filter results. An interceptor may +// require, for example, that a `DELETE` statement includes a WHERE with a UNIQUE KEY column with Equals operator +// to ensure we're not doing anything too risky. +func (e *TabletVExec) AnalyzeQuery(ctx context.Context, query string) (err error) { + if e.Stmt, err = sqlparser.Parse(query); err != nil { + return err + } + e.Query = query + if err := e.analyzeStatement(); err != nil { + return err + } + return nil +} diff --git a/go/vt/vttablet/vexec/vexec_test.go b/go/vt/vttablet/vexec/vexec_test.go new file mode 100644 index 00000000000..a159dfcfde1 --- /dev/null +++ b/go/vt/vttablet/vexec/vexec_test.go @@ -0,0 +1,202 @@ +/* +Copyright 2019 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vexec + +import ( + "context" + "testing" + + "vitess.io/vitess/go/vt/sqlparser" + + "github.com/stretchr/testify/assert" +) + +const ( + tWorkflow = "myworkflow" + tKeyspace = "mykeyspace" +) + +func TestNewTabletVExec(t *testing.T) { + vx := NewTabletVExec(tWorkflow, tKeyspace) + assert.NotNil(t, vx) + assert.Equal(t, vx.Workflow, tWorkflow) + assert.Equal(t, vx.Keyspace, tKeyspace) +} + +func TestAnalyzeQuerySelect1(t *testing.T) { + query := `select migration_status, strategy from _vt.schema_migrations where migration_uuid='123'` + vx := NewTabletVExec(tWorkflow, tKeyspace) + err := vx.AnalyzeQuery(context.Background(), query) + assert.NoError(t, err) + + assert.Equal(t, vx.Query, query) + assert.Equal(t, vx.TableName, "_vt.schema_migrations") + + _, ok := vx.WhereCols["migration_uuid"] + assert.True(t, ok) + _, ok = vx.WhereCols["strategy"] + assert.False(t, ok) + + _, ok = vx.UpdateCols["strategy"] + assert.False(t, ok) +} +func TestAnalyzeQuerySelect2(t *testing.T) { + query := `select migration_status, strategy from _vt.schema_migrations where migration_uuid='123' or requested_timestamp 0 { + // we must never allow changing an immutable column + for _, expr := range upd.Exprs { + for _, immutableColName := range plannerParams.immutableColumnNames { + if expr.Name.Name.EqualString(immutableColName) { + return nil, fmt.Errorf("%s cannot be changed: %v", immutableColName, sqlparser.String(expr)) + } + } } } - - upd.Where = vx.addDefaultWheres(upd.Where) + if updatableColumnNames := plannerParams.updatableColumnNames; len(updatableColumnNames) > 0 { + // if updatableColumnNames is non empty, then we must only accept changes to columns listed there + for _, expr := range upd.Exprs { + isUpdatable := false + for _, updatableColName := range updatableColumnNames { + if expr.Name.Name.EqualString(updatableColName) { + isUpdatable = true + } + } + if !isUpdatable { + return nil, fmt.Errorf("%+v cannot be changed: %v", expr.Name.Name, sqlparser.String(expr)) + } + } + } + if templates := plannerParams.updateTemplates; len(templates) > 0 { + match, err := sqlparser.QueryMatchesTemplates(vx.query, templates) + if err != nil { + return nil, err + } + if !match { + return nil, fmt.Errorf("Query must match one of these templates: %s", strings.Join(templates, "; ")) + } + } + upd.Where = vx.addDefaultWheres(planner, upd.Where) buf := sqlparser.NewTrackedBuffer(nil) buf.Myprintf("%v", upd) @@ -159,13 +330,8 @@ func (vx *vexec) buildUpdatePlan(upd *sqlparser.Update) (*vexecPlan, error) { }, nil } -func (vx *vexec) buildDeletePlan(del *sqlparser.Delete) (*vexecPlan, error) { - switch sqlparser.String(del.TableExprs) { - case vreplicationTableName: - // no-op - default: - return nil, fmt.Errorf("invalid table name: %v", sqlparser.String(del.TableExprs)) - } +// buildUpdatePlan builds a plan for a DELETE query +func (vx *vexec) buildDeletePlan(ctx context.Context, planner vexecPlanner, del *sqlparser.Delete) (*vexecPlan, error) { if del.Targets != nil { return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(del)) } @@ -176,7 +342,7 @@ func (vx *vexec) buildDeletePlan(del *sqlparser.Delete) (*vexecPlan, error) { return nil, fmt.Errorf("unsupported construct: %v", sqlparser.String(del)) } - del.Where = vx.addDefaultWheres(del.Where) + del.Where = vx.addDefaultWheres(planner, del.Where) buf := sqlparser.NewTrackedBuffer(nil) buf.Myprintf("%v", del) @@ -187,14 +353,37 @@ func (vx *vexec) buildDeletePlan(del *sqlparser.Delete) (*vexecPlan, error) { }, nil } -func (vx *vexec) buildSelectPlan(sel *sqlparser.Select) (*vexecPlan, error) { - switch sqlparser.String(sel.From) { - case vreplicationTableName: - // no-op - default: - return nil, fmt.Errorf("invalid table name: %v", sqlparser.String(sel.From)) +// buildInsertPlan builds a plan for a INSERT query +func (vx *vexec) buildInsertPlan(ctx context.Context, planner vexecPlanner, ins *sqlparser.Insert) (*vexecPlan, error) { + plannerParams := planner.params() + templates := plannerParams.insertTemplates + if len(templates) == 0 { + // at this time INSERT is only supported if an insert template exists + // Remove this conditional if there's any new case for INSERT + return nil, fmt.Errorf("query not supported by vexec: %s", sqlparser.String(ins)) + } + if len(templates) > 0 { + match, err := sqlparser.QueryMatchesTemplates(vx.query, templates) + if err != nil { + return nil, err + } + if !match { + return nil, fmt.Errorf("Query must match one of these templates: %s", strings.Join(templates, "; ")) + } } - sel.Where = vx.addDefaultWheres(sel.Where) + + buf := sqlparser.NewTrackedBuffer(nil) + buf.Myprintf("%v", ins) + + return &vexecPlan{ + opcode: insertQuery, + parsedQuery: buf.ParsedQuery(), + }, nil +} + +// buildUpdatePlan builds a plan for a SELECT query +func (vx *vexec) buildSelectPlan(ctx context.Context, planner vexecPlanner, sel *sqlparser.Select) (*vexecPlan, error) { + sel.Where = vx.addDefaultWheres(planner, sel.Where) buf := sqlparser.NewTrackedBuffer(nil) buf.Myprintf("%v", sel) diff --git a/go/vt/wrangler/vexec_test.go b/go/vt/wrangler/vexec_test.go index d0d1fcad095..6af98a62add 100644 --- a/go/vt/wrangler/vexec_test.go +++ b/go/vt/wrangler/vexec_test.go @@ -54,7 +54,8 @@ func TestVExec(t *testing.T) { } sort.Strings(shards) require.Equal(t, fmt.Sprintf("%v", shards), "[-80 80-]") - plan, err := vx.buildVExecPlan() + + plan, err := vx.parseAndPlan(ctx) require.NoError(t, err) require.NotNil(t, plan) @@ -70,8 +71,8 @@ func TestVExec(t *testing.T) { want := addWheres(query) require.Equal(t, want, plan.parsedQuery.Query) - query = plan.parsedQuery.Query - vx.exec(query) + vx.plannedQuery = plan.parsedQuery.Query + vx.exec() type TestCase struct { name string @@ -118,7 +119,7 @@ func TestVExec(t *testing.T) { errorString: errorString, }) - errorString = "invalid table name" + errorString = "table not supported by vexec" testCases = append(testCases, &TestCase{ name: "delete invalid-other-table", query: "delete from _vt.copy_state", @@ -355,7 +356,7 @@ func TestVExecValidations(t *testing.T) { { name: "incorrect table", query: "select * from _vt.vreplication2", - errorString: "invalid table name: _vt.vreplication2", + errorString: "table not supported by vexec: _vt.vreplication2", }, { name: "unsupported query", @@ -366,7 +367,7 @@ func TestVExecValidations(t *testing.T) { for _, bq := range badQueries { t.Run(bq.name, func(t *testing.T) { vx.query = bq.query - plan, err := vx.buildVExecPlan() + plan, err := vx.parseAndPlan(ctx) require.EqualError(t, err, bq.errorString) require.Nil(t, plan) }) diff --git a/proto/tabletmanagerdata.proto b/proto/tabletmanagerdata.proto index b684e401713..b7e6e32c5bb 100644 --- a/proto/tabletmanagerdata.proto +++ b/proto/tabletmanagerdata.proto @@ -536,3 +536,13 @@ message SlaveWasRestartedRequest { // Deprecated message SlaveWasRestartedResponse { } + +message VExecRequest { + string query = 1; + string workflow = 2; + string keyspace = 3; +} + +message VExecResponse { + query.QueryResult result = 1; +} diff --git a/proto/tabletmanagerservice.proto b/proto/tabletmanagerservice.proto index d00b1dfd3bf..4fc66525f39 100644 --- a/proto/tabletmanagerservice.proto +++ b/proto/tabletmanagerservice.proto @@ -189,4 +189,7 @@ service TabletManager { // Deprecated rpc SlaveWasRestarted(tabletmanagerdata.SlaveWasRestartedRequest) returns (tabletmanagerdata.SlaveWasRestartedResponse) {}; + + // Generic VExec request. Can be used for various purposes + rpc VExec(tabletmanagerdata.VExecRequest) returns(tabletmanagerdata.VExecResponse) {}; } diff --git a/resources/bin/gh-ost b/resources/bin/gh-ost new file mode 100644 index 00000000000..299ebfb846b Binary files /dev/null and b/resources/bin/gh-ost differ diff --git a/test/config.json b/test/config.json index 269d178ba9d..1eb254051f4 100644 --- a/test/config.json +++ b/test/config.json @@ -266,6 +266,15 @@ "site_test" ] }, + "onlineddl": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/onlineddl"], + "Command": [], + "Manual": false, + "Shard": 26, + "RetryMax": 0, + "Tags": [] + }, "pitr": { "File": "unused.go", "Args": ["vitess.io/vitess/go/test/endtoend/recovery/pitr"],