diff --git a/data/test/tabletserver/exec_cases.txt b/data/test/tabletserver/exec_cases.txt index aa644d63609..133d8df567d 100644 --- a/data/test/tabletserver/exec_cases.txt +++ b/data/test/tabletserver/exec_cases.txt @@ -25,7 +25,7 @@ "FullQuery": "select distinct * from a limit :#maxLimit" } -# grouy by +# group by "select * from a group by b" { "PlanID": "PASS_SELECT", @@ -186,6 +186,15 @@ "FullQuery": "insert into b.a(eid, id) values (1, :a)" } +# insert cross-db +options:PassthroughDMLs +"insert into b.a (eid, id) values (1, :a)" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "insert into b.a(eid, id) values (1, :a)" +} + # insert with bind value "insert into a (eid, id) values (1, :a)" { @@ -196,6 +205,15 @@ "PKValues": [[1], [":a"]] } +# insert with bind value +options:PassthroughDMLs +"insert into a (eid, id) values (1, :a)" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "insert into a(eid, id) values (1, :a)" +} + # default number "insert into a (id) values (1)" { @@ -307,6 +325,15 @@ "PKValues": [[1], [2]] } +# upsert multiple unique index +options:PassthroughDMLs +"insert into a (eid, id) values (1, 2) on duplicate key update name = func(a)" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "insert into a(eid, id) values (1, 2) on duplicate key update name = func(a)" +} + # upsert single unique index "insert into b (eid, id) values (1, 2) on duplicate key update name = func(a)" { @@ -610,6 +637,15 @@ "FullQuery": "replace into b(eid, id) values (1, 2), (3, 4)" } +# multi-row +options:PassthroughDMLs +"replace into b (eid, id) values (1, 2), (3, 4)" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "replace into b(eid, id) values (1, 2), (3, 4)" +} + # single-row with set "replace into b set eid = 1, id = 2" { @@ -648,6 +684,15 @@ "WhereClause": " where name in ('a', 'b')" } +# update limit with pk +options:PassthroughDMLs +"update d set foo='foo' where name in ('a', 'b') limit 1" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "update d set foo = 'foo' where name in ('a', 'b') limit 1" +} + # update cross-db "update b.a set name='foo' where eid=1 and id=1" { @@ -657,6 +702,15 @@ "FullQuery": "update b.a set name = 'foo' where eid = 1 and id = 1" } +# update cross-db +options:PassthroughDMLs +"update b.a set name='foo' where eid=1 and id=1" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "update b.a set name = 'foo' where eid = 1 and id = 1" +} + # multi-table update "update a, b set a.name = 'foo' where a.id = b.id and b.var = 'test'" { @@ -865,6 +919,15 @@ "WhereClause": " where name in ('a', 'b')" } +# delete limit with pk +options:PassthroughDMLs +"delete from d where name in ('a', 'b') limit 1" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "delete from d where name in ('a', 'b') limit 1" +} + # delete cross-db "delete from b.a where eid=1 and id=1" { @@ -907,6 +970,15 @@ "WhereClause": " where eid = 1 and id = 1" } +# pk +options:PassthroughDMLs +"delete from a where eid=1 and id=1" +{ + "PlanID": "PASS_DML", + "TableName": "", + "FullQuery": "delete from a where eid = 1 and id = 1" +} + # partial pk "delete from a where eid=1" { diff --git a/data/test/vtexplain/multi-output/deletesharded-output.txt b/data/test/vtexplain/multi-output/deletesharded-output.txt index 52b6d862319..65df48ce6fa 100644 --- a/data/test/vtexplain/multi-output/deletesharded-output.txt +++ b/data/test/vtexplain/multi-output/deletesharded-output.txt @@ -3,7 +3,7 @@ delete from music_extra where id=1 1 ks_sharded/-40: begin 1 ks_sharded/-40: delete from music_extra where id in (1) /* vtgate:: keyspace_id:166b40b44aba4bd6 */ -2 ks_sharded/-40: commit +1 ks_sharded/-40: commit ---------------------------------------------------------------------- delete from music_extra where id=1 and extra='abc' @@ -11,7 +11,7 @@ delete from music_extra where id=1 and extra='abc' 1 ks_sharded/-40: begin 1 ks_sharded/-40: select id from music_extra where id = 1 and extra = 'abc' limit 10001 for update /* vtgate:: keyspace_id:166b40b44aba4bd6 */ 1 ks_sharded/-40: delete from music_extra where id in (1) /* vtgate:: keyspace_id:166b40b44aba4bd6 */ -2 ks_sharded/-40: commit +1 ks_sharded/-40: commit ---------------------------------------------------------------------- delete from user where id=1 diff --git a/data/test/vtexplain/multi-output/unsharded-output.txt b/data/test/vtexplain/multi-output/unsharded-output.txt index 4b6af782c14..e5ece7403a1 100644 --- a/data/test/vtexplain/multi-output/unsharded-output.txt +++ b/data/test/vtexplain/multi-output/unsharded-output.txt @@ -8,7 +8,7 @@ insert into t1 (id,intval,floatval) values (1,2,3.14) 1 ks_unsharded/-: begin 1 ks_unsharded/-: insert into t1(id, intval, floatval) values (1, 2, 3.14) -2 ks_unsharded/-: commit +1 ks_unsharded/-: commit ---------------------------------------------------------------------- update t1 set intval = 10 @@ -16,7 +16,7 @@ update t1 set intval = 10 1 ks_unsharded/-: begin 1 ks_unsharded/-: select id from t1 limit 10001 for update 1 ks_unsharded/-: update t1 set intval = 10 where id in (1) -2 ks_unsharded/-: commit +1 ks_unsharded/-: commit ---------------------------------------------------------------------- update t1 set floatval = 9.99 @@ -24,20 +24,20 @@ update t1 set floatval = 9.99 1 ks_unsharded/-: begin 1 ks_unsharded/-: select id from t1 limit 10001 for update 1 ks_unsharded/-: update t1 set floatval = 9.99 where id in (1) -2 ks_unsharded/-: commit +1 ks_unsharded/-: commit ---------------------------------------------------------------------- delete from t1 where id = 100 1 ks_unsharded/-: begin 1 ks_unsharded/-: delete from t1 where id in (100) -2 ks_unsharded/-: commit +1 ks_unsharded/-: commit ---------------------------------------------------------------------- insert into t1 (id,intval,floatval) values (1,2,3.14) on duplicate key update intval=3, floatval=3.14 1 ks_unsharded/-: begin 1 ks_unsharded/-: insert into t1(id, intval, floatval) values (1, 2, 3.14) on duplicate key update intval = 3, floatval = 3.14 -2 ks_unsharded/-: commit +1 ks_unsharded/-: commit ---------------------------------------------------------------------- diff --git a/data/test/vtexplain/multi-output/updatesharded-output.txt b/data/test/vtexplain/multi-output/updatesharded-output.txt index 62b02b7bea9..6e5a18f3fec 100644 --- a/data/test/vtexplain/multi-output/updatesharded-output.txt +++ b/data/test/vtexplain/multi-output/updatesharded-output.txt @@ -3,7 +3,7 @@ update user set nickname='alice' where id=1 1 ks_sharded/-40: begin 1 ks_sharded/-40: update user set nickname = 'alice' where id in (1) /* vtgate:: keyspace_id:166b40b44aba4bd6 */ -2 ks_sharded/-40: commit +1 ks_sharded/-40: commit ---------------------------------------------------------------------- update user set nickname='alice' where name='alice' @@ -21,7 +21,7 @@ update user set pet='fido' where id=1 1 ks_sharded/-40: begin 1 ks_sharded/-40: update user set pet = 'fido' where id in (1) /* vtgate:: keyspace_id:166b40b44aba4bd6 */ -2 ks_sharded/-40: commit +1 ks_sharded/-40: commit ---------------------------------------------------------------------- update user set name='alicia' where id=1 diff --git a/docker/k8s/Dockerfile b/docker/k8s/Dockerfile new file mode 100644 index 00000000000..ce7cd358d10 --- /dev/null +++ b/docker/k8s/Dockerfile @@ -0,0 +1,58 @@ +FROM vitess/base AS base + +FROM debian:stretch-slim + +# Set up Vitess environment (just enough to run pre-built Go binaries) +ENV VTROOT /vt +ENV VTDATAROOT /vtdataroot +ENV VTTOP /vt/src/github.com/youtube/vitess + +# Prepare directory structure. +RUN mkdir -p /vt && \ + mkdir -p /vt/bin && \ + mkdir -p /vt/config && \ + mkdir -p /vt/web && \ + mkdir -p /vtdataroot/tabletdata + +# Copy CA certs for https calls +COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt + +# Copy binaries +COPY --from=base /vt/bin/mysqlctld /vt/bin/ +COPY --from=base /vt/bin/vtctld /vt/bin/ +COPY --from=base /vt/bin/vtctl /vt/bin/ +COPY --from=base /vt/bin/vtgate /vt/bin/ +COPY --from=base /vt/bin/vttablet /vt/bin/ +COPY --from=base /vt/bin/vtworker /vt/bin/ + +# copy web admin files +COPY --from=base $VTTOP/web /vt/web/ + +# copy vitess config +COPY --from=base $VTTOP/config/init_db.sql /vt/config/ + +# mysql flavor files for db specific .cnf settings +COPY --from=base $VTTOP/config/mycnf/master_mysql56.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/master_mariadb.cnf /vt/config/mycnf/ + +# settings for different types of instances +COPY --from=base $VTTOP/config/mycnf/default.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/master.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/replica.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/rdonly.cnf /vt/config/mycnf/ +COPY --from=base $VTTOP/config/mycnf/backup.cnf /vt/config/mycnf/ + +# settings to support rbr +COPY --from=base $VTTOP/config/mycnf/rbr.cnf /vt/config/mycnf/ + +# add vitess user and add permissions +RUN groupadd -r --gid 999 vitess && useradd -r -g vitess --uid 999 vitess && \ + chown -R vitess:vitess /vt; + +# TODO: remove when https://github.com/youtube/vitess/issues/3553 is fixed +RUN apt-get update && \ + apt-get upgrade -qq && \ + apt-get install mysql-client -qq --no-install-recommends && \ + apt-get autoremove && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/go/cmd/automation_server/automation_server.go b/go/cmd/automation_server/automation_server.go index c34b360dafe..af01e894f1c 100644 --- a/go/cmd/automation_server/automation_server.go +++ b/go/cmd/automation_server/automation_server.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "flag" "fmt" "net" "os" @@ -34,13 +33,7 @@ func init() { } func main() { - - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } + servenv.ParseFlags("automation_server") fmt.Println("Automation Server, listening on:", *servenv.Port) diff --git a/go/cmd/l2vtgate/main.go b/go/cmd/l2vtgate/main.go index dd082656c8e..a1da649a7be 100644 --- a/go/cmd/l2vtgate/main.go +++ b/go/cmd/l2vtgate/main.go @@ -19,7 +19,6 @@ package main import ( "flag" "math/rand" - "os" "strings" "time" @@ -55,14 +54,9 @@ func init() { func main() { defer exit.Recover() - flag.Parse() + servenv.ParseFlags("l2vtgate") servenv.Init() - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - ts := topo.Open() defer ts.Close() diff --git a/go/cmd/mysqlctld/mysqlctld.go b/go/cmd/mysqlctld/mysqlctld.go index 2c7e46e8180..4fbef020f9f 100644 --- a/go/cmd/mysqlctld/mysqlctld.go +++ b/go/cmd/mysqlctld/mysqlctld.go @@ -58,12 +58,7 @@ func main() { // mysqlctld only starts and stops mysql, only needs dba. dbconfigFlags := dbconfigs.DbaConfig dbconfigs.RegisterFlags(dbconfigFlags) - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } + servenv.ParseFlags("mysqlctld") // We'll register this OnTerm handler before mysqld starts, so we get notified // if mysqld dies on its own without us (or our RPC client) telling it to. diff --git a/go/cmd/vtcombo/main.go b/go/cmd/vtcombo/main.go index 43729f70d83..09e40e675cc 100644 --- a/go/cmd/vtcombo/main.go +++ b/go/cmd/vtcombo/main.go @@ -23,7 +23,6 @@ package main import ( "flag" - "os" "strings" "time" @@ -67,18 +66,7 @@ func main() { dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(dbconfigFlags) mysqlctl.RegisterFlags() - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - - if len(flag.Args()) > 0 { - flag.Usage() - log.Errorf("vtcombo doesn't take any positional arguments") - exit.Return(1) - } + servenv.ParseFlags("vtcombo") // parse the input topology tpb := &vttestpb.VTTestTopology{} diff --git a/go/cmd/vtctl/vtctl.go b/go/cmd/vtctl/vtctl.go index eb7414d8fe2..37a1b3eec81 100644 --- a/go/cmd/vtctl/vtctl.go +++ b/go/cmd/vtctl/vtctl.go @@ -69,19 +69,7 @@ func main() { defer exit.RecoverAll() defer logutil.Flush() - flag.Parse() - args := flag.Args() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - - if len(args) == 0 { - flag.Usage() - exit.Return(1) - } - + args := servenv.ParseFlagsWithArgs("vtctl") action := args[0] startMsg := fmt.Sprintf("USER=%v SUDO_USER=%v %v", os.Getenv("USER"), os.Getenv("SUDO_USER"), strings.Join(os.Args, " ")) diff --git a/go/cmd/vtctld/main.go b/go/cmd/vtctld/main.go index 3cfcff48ece..82d859a7b2e 100644 --- a/go/cmd/vtctld/main.go +++ b/go/cmd/vtctld/main.go @@ -17,9 +17,6 @@ limitations under the License. package main import ( - "flag" - "os" - "github.com/youtube/vitess/go/vt/servenv" "github.com/youtube/vitess/go/vt/topo" "github.com/youtube/vitess/go/vt/vtctld" @@ -35,15 +32,10 @@ var ( ) func main() { - flag.Parse() + servenv.ParseFlags("vtctld") servenv.Init() defer servenv.Close() - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - ts = topo.Open() defer ts.Close() diff --git a/go/cmd/vtexplain/vtexplain.go b/go/cmd/vtexplain/vtexplain.go index 0a2056c329a..d676bb839d2 100644 --- a/go/cmd/vtexplain/vtexplain.go +++ b/go/cmd/vtexplain/vtexplain.go @@ -20,7 +20,6 @@ import ( "flag" "fmt" "io/ioutil" - "os" log "github.com/golang/glog" "github.com/youtube/vitess/go/exit" @@ -124,19 +123,7 @@ func main() { defer exit.RecoverAll() defer logutil.Flush() - flag.Parse() - - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - - args := flag.Args() - - if len(args) != 0 { - flag.Usage() - exit.Return(1) - } + servenv.ParseFlags("vtexplain") err := parseAndRun() if err != nil { diff --git a/go/cmd/vtgate/vtgate.go b/go/cmd/vtgate/vtgate.go index 3c2d9c33260..c27ffa303eb 100644 --- a/go/cmd/vtgate/vtgate.go +++ b/go/cmd/vtgate/vtgate.go @@ -19,7 +19,6 @@ package main import ( "flag" "math/rand" - "os" "strings" "time" @@ -59,14 +58,9 @@ func init() { func main() { defer exit.Recover() - flag.Parse() + servenv.ParseFlags("vtgate") servenv.Init() - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - if initFakeZK != nil { initFakeZK() } diff --git a/go/cmd/vtgateclienttest/main.go b/go/cmd/vtgateclienttest/main.go index e713168d405..421114b8bf7 100644 --- a/go/cmd/vtgateclienttest/main.go +++ b/go/cmd/vtgateclienttest/main.go @@ -20,9 +20,6 @@ limitations under the License. package main import ( - "flag" - "os" - "github.com/youtube/vitess/go/cmd/vtgateclienttest/services" "github.com/youtube/vitess/go/exit" "github.com/youtube/vitess/go/vt/servenv" @@ -36,14 +33,9 @@ func init() { func main() { defer exit.Recover() - flag.Parse() + servenv.ParseFlags("vtgateclienttest") servenv.Init() - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } - // The implementation chain. servenv.OnRun(func() { s := services.CreateServices() diff --git a/go/cmd/vttablet/vttablet.go b/go/cmd/vttablet/vttablet.go index 7b0a0c9a97d..fec142f4294 100644 --- a/go/cmd/vttablet/vttablet.go +++ b/go/cmd/vttablet/vttablet.go @@ -19,7 +19,6 @@ package main import ( "flag" - "os" log "github.com/golang/glog" "github.com/youtube/vitess/go/vt/dbconfigs" @@ -52,17 +51,9 @@ func main() { dbconfigs.FilteredConfig | dbconfigs.ReplConfig dbconfigs.RegisterFlags(dbconfigFlags) mysqlctl.RegisterFlags() - flag.Parse() - if *servenv.Version { - servenv.AppVersion.Print() - os.Exit(0) - } + servenv.ParseFlags("vttablet") - if len(flag.Args()) > 0 { - flag.Usage() - log.Exit("vttablet doesn't take any positional arguments") - } if err := tabletenv.VerifyConfig(); err != nil { log.Exitf("invalid config: %v", err) } diff --git a/go/vt/servenv/servenv.go b/go/vt/servenv/servenv.go index 259648c5907..350b85064f9 100644 --- a/go/vt/servenv/servenv.go +++ b/go/vt/servenv/servenv.go @@ -33,6 +33,7 @@ import ( "net/url" "os" "runtime" + "strings" "sync" "syscall" "time" @@ -193,3 +194,37 @@ func RegisterDefaultFlags() { func RunDefault() { Run(*Port) } + +// ParseFlags initializes flags and handles the common case when no positional +// arguments are expected. +func ParseFlags(cmd string) { + flag.Parse() + + if *Version { + AppVersion.Print() + os.Exit(0) + } + + args := flag.Args() + if len(args) > 0 { + flag.Usage() + log.Exitf("%s doesn't take any positional arguments, got '%s'", cmd, strings.Join(args, " ")) + } +} + +// ParseFlagsWithArgs initializes flags and returns the positional arguments +func ParseFlagsWithArgs(cmd string) []string { + flag.Parse() + + if *Version { + AppVersion.Print() + os.Exit(0) + } + + args := flag.Args() + if len(args) == 0 { + log.Exitf("%s expected at least one positional argument", cmd) + } + + return args +} diff --git a/go/vt/sqlparser/analyzer.go b/go/vt/sqlparser/analyzer.go index 08d3ccb6e06..97bd8aeaa80 100644 --- a/go/vt/sqlparser/analyzer.go +++ b/go/vt/sqlparser/analyzer.go @@ -45,6 +45,7 @@ const ( StmtUse StmtOther StmtUnknown + StmtComment ) // Preview analyzes the beginning of the query using a simpler and faster @@ -91,6 +92,9 @@ func Preview(sql string) int { case "analyze", "describe", "desc", "explain", "repair", "optimize", "truncate": return StmtOther } + if strings.Index(trimmed, "/*!") == 0 { + return StmtComment + } return StmtUnknown } diff --git a/go/vt/sqlparser/analyzer_test.go b/go/vt/sqlparser/analyzer_test.go index c345feb70ff..c8f6ec0ed3d 100644 --- a/go/vt/sqlparser/analyzer_test.go +++ b/go/vt/sqlparser/analyzer_test.go @@ -66,6 +66,8 @@ func TestPreview(t *testing.T) { {"/* leading comment */ select ...", StmtSelect}, {"/* leading comment */ /* leading comment 2 */ select ...", StmtSelect}, + {"/*! MySQL-specific comment */", StmtComment}, + {"/*!50708 MySQL-version comment */", StmtComment}, {"-- leading single line comment \n select ...", StmtSelect}, {"-- leading single line comment \n -- leading single line comment 2\n select ...", StmtSelect}, diff --git a/go/vt/sqlparser/comments.go b/go/vt/sqlparser/comments.go index 62ad15e063e..b5ac471df5e 100644 --- a/go/vt/sqlparser/comments.go +++ b/go/vt/sqlparser/comments.go @@ -121,6 +121,10 @@ func StripLeadingComments(sql string) string { if index <= 1 { return sql } + // don't strip /*! ... */ or /*!50700 ... */ + if len(sql) > 2 && sql[2] == '!' { + return sql + } sql = sql[index+2:] case '-': // Single line comment @@ -140,3 +144,15 @@ func StripLeadingComments(sql string) string { func hasCommentPrefix(sql string) bool { return len(sql) > 1 && ((sql[0] == '/' && sql[1] == '*') || (sql[0] == '-' && sql[1] == '-')) } + +// ExtractMysqlComment extracts the version and SQL from a comment-only query +// such as /*!50708 sql here */ +func ExtractMysqlComment(sql string) (version string, innerSQL string) { + sql = sql[3 : len(sql)-2] + + endOfVersionIndex := strings.IndexFunc(sql, func(c rune) bool { return !unicode.IsDigit(c) }) + version = sql[0:endOfVersionIndex] + innerSQL = strings.TrimFunc(sql[endOfVersionIndex:], unicode.IsSpace) + + return version, innerSQL +} diff --git a/go/vt/sqlparser/comments_test.go b/go/vt/sqlparser/comments_test.go index f23c4f99e0c..d174a9aa10d 100644 --- a/go/vt/sqlparser/comments_test.go +++ b/go/vt/sqlparser/comments_test.go @@ -128,6 +128,12 @@ func TestStripLeadingComments(t *testing.T) { }, { input: "/**/", outSQL: "", + }, { + input: "/*!*/", + outSQL: "/*!*/", + }, { + input: "/*!a*/", + outSQL: "/*!a*/", }, { input: "/*b*/ /*a*/", outSQL: "", @@ -167,3 +173,31 @@ a`, } } } + +func TestExtractMysqlComment(t *testing.T) { + var testCases = []struct { + input, outSQL, outVersion string + }{{ + input: "/*!50708SET max_execution_time=5000 */", + outSQL: "SET max_execution_time=5000", + outVersion: "50708", + }, { + input: "/*!50708 SET max_execution_time=5000*/", + outSQL: "SET max_execution_time=5000", + outVersion: "50708", + }, { + input: "/*! SET max_execution_time=5000*/", + outSQL: "SET max_execution_time=5000", + outVersion: "", + }} + for _, testCase := range testCases { + gotVersion, gotSQL := ExtractMysqlComment(testCase.input) + + if gotVersion != testCase.outVersion { + t.Errorf("test input: '%s', got version\n%+v, want\n%+v", testCase.input, gotVersion, testCase.outVersion) + } + if gotSQL != testCase.outSQL { + t.Errorf("test input: '%s', got SQL\n%+v, want\n%+v", testCase.input, gotSQL, testCase.outSQL) + } + } +} diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index e72baf6f2d2..bda1920747f 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -1280,6 +1280,12 @@ func TestKeywords(t *testing.T) { }, { input: "select /* unused keywords as cols */ write, varying from t where trailing = 'foo'", output: "select /* unused keywords as cols */ `write`, `varying` from t where `trailing` = 'foo'", + }, { + input: "select status from t", + output: "select `status` from t", + }, { + input: "select variables from t", + output: "select `variables` from t", }} for _, tcase := range validSQL { diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index fa8e456511b..06ca8ce7717 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -516,18 +516,18 @@ var yyExca = [...]int{ -1, 3, 5, 22, -2, 4, - -1, 200, - 79, 599, - 108, 599, - -2, 42, -1, 202, - 79, 622, - 108, 622, + 79, 597, + 108, 597, + -2, 42, + -1, 204, + 79, 620, + 108, 620, -2, 44, - -1, 206, + -1, 208, 108, 496, -2, 492, - -1, 207, + -1, 209, 108, 497, -2, 493, -1, 638, @@ -552,838 +552,842 @@ var yyExca = [...]int{ const yyPrivate = 57344 -const yyLast = 8186 +const yyLast = 8230 var yyAct = [...]int{ - 380, 38, 1053, 565, 430, 3, 353, 885, 340, 624, - 908, 236, 664, 194, 432, 44, 886, 882, 677, 169, - 943, 429, 736, 238, 379, 973, 355, 848, 743, 856, - 637, 746, 640, 785, 641, 797, 713, 650, 342, 38, - 818, 760, 351, 168, 402, 408, 782, 174, 673, 658, - 209, 197, 189, 418, 184, 603, 43, 1084, 163, 1075, - 203, 1081, 434, 1070, 185, 178, 1079, 1074, 956, 1008, - 213, 1030, 814, 183, 229, 1069, 657, 985, 188, 913, - 914, 915, 665, 1003, 1036, 1001, 693, 219, 916, 334, - 335, 149, 944, 164, 165, 166, 167, 1078, 1076, 1054, - 691, 1056, 531, 530, 540, 541, 533, 534, 535, 536, - 537, 538, 539, 532, 946, 159, 542, 838, 604, 835, - 220, 215, 577, 132, 131, 837, 132, 697, 497, 207, - 348, 625, 627, 492, 796, 231, 690, 233, 795, 1046, - 794, 948, 1028, 952, 211, 947, 216, 945, 235, 235, - 235, 235, 950, 235, 235, 63, 230, 232, 143, 141, - 235, 949, 141, 652, 133, 144, 951, 953, 134, 135, - 136, 146, 48, 554, 555, 38, 152, 148, 993, 405, - 819, 141, 141, 970, 687, 692, 685, 141, 404, 860, - 431, 210, 665, 50, 51, 52, 53, 150, 652, 801, - 154, 564, 203, 626, 450, 695, 698, 224, 446, 444, - 922, 542, 228, 235, 917, 836, 188, 834, 235, 517, - 745, 520, 1057, 145, 222, 720, 808, 235, 235, 235, - 235, 235, 235, 235, 235, 689, 1068, 1029, 1027, 718, - 719, 717, 147, 153, 155, 156, 157, 158, 504, 688, - 161, 160, 449, 651, 532, 502, 958, 542, 649, 648, - 923, 141, 761, 141, 519, 518, 1049, 141, 866, 494, - 865, 592, 593, 141, 694, 867, 812, 63, 63, 63, - 63, 520, 63, 63, 410, 696, 519, 518, 651, 63, - 531, 530, 540, 541, 533, 534, 535, 536, 537, 538, - 539, 532, 989, 520, 542, 535, 536, 537, 538, 539, - 532, 518, 141, 542, 1063, 519, 518, 519, 518, 141, - 141, 141, 960, 519, 518, 654, 63, 520, 849, 341, - 655, 761, 520, 872, 520, 235, 235, 841, 842, 843, - 520, 988, 63, 41, 141, 827, 141, 63, 406, 141, - 551, 553, 141, 716, 141, 826, 63, 63, 63, 63, - 63, 63, 63, 63, 815, 531, 530, 540, 541, 533, - 534, 535, 536, 537, 538, 539, 532, 552, 563, 542, - 1039, 567, 568, 569, 570, 571, 572, 573, 987, 576, + 380, 38, 1053, 565, 908, 664, 196, 885, 886, 624, + 171, 882, 430, 3, 736, 429, 973, 432, 677, 379, + 340, 353, 943, 44, 746, 240, 743, 641, 637, 856, + 848, 236, 640, 797, 760, 818, 713, 650, 785, 38, + 342, 782, 351, 165, 408, 238, 402, 176, 603, 199, + 434, 170, 191, 43, 211, 1084, 1075, 180, 1081, 673, + 1070, 418, 1079, 1074, 1069, 956, 1008, 185, 215, 1030, + 814, 657, 985, 1036, 665, 205, 48, 1003, 166, 167, + 168, 169, 1001, 231, 334, 335, 1078, 913, 914, 915, + 658, 1076, 187, 1054, 838, 186, 916, 50, 51, 52, + 53, 221, 604, 222, 1028, 217, 133, 693, 134, 531, + 530, 540, 541, 533, 534, 535, 536, 537, 538, 539, + 532, 691, 348, 542, 577, 134, 1056, 531, 530, 540, + 541, 533, 534, 535, 536, 537, 538, 539, 532, 355, + 497, 542, 492, 835, 233, 218, 235, 849, 697, 837, + 237, 237, 237, 237, 145, 237, 237, 690, 136, 137, + 138, 796, 237, 795, 794, 232, 234, 19, 39, 21, + 22, 213, 135, 625, 627, 554, 555, 38, 1046, 993, + 745, 665, 331, 332, 333, 33, 336, 337, 970, 405, + 23, 190, 431, 339, 860, 801, 564, 450, 404, 1029, + 1027, 819, 226, 922, 444, 687, 692, 685, 532, 32, + 652, 542, 542, 41, 652, 237, 517, 520, 449, 205, + 237, 230, 917, 958, 761, 1068, 695, 698, 944, 237, + 237, 237, 237, 237, 237, 237, 237, 494, 808, 836, + 224, 834, 212, 720, 446, 626, 491, 1057, 812, 1049, + 946, 496, 504, 923, 406, 502, 689, 718, 719, 717, + 505, 506, 507, 508, 509, 510, 511, 512, 518, 761, + 688, 872, 25, 26, 28, 27, 30, 948, 341, 952, + 410, 947, 1063, 945, 520, 31, 34, 35, 950, 41, + 36, 37, 29, 654, 866, 694, 865, 949, 655, 716, + 651, 1039, 951, 953, 651, 989, 696, 209, 988, 649, + 648, 827, 519, 518, 531, 530, 540, 541, 533, 534, + 535, 536, 537, 538, 539, 532, 826, 815, 542, 520, + 737, 190, 738, 63, 987, 237, 237, 143, 825, 921, + 143, 910, 533, 534, 535, 536, 537, 538, 539, 532, + 551, 553, 542, 535, 536, 537, 538, 539, 532, 143, + 143, 542, 40, 1065, 341, 143, 513, 514, 540, 541, + 533, 534, 535, 536, 537, 538, 539, 532, 563, 809, + 542, 567, 568, 569, 570, 571, 572, 573, 739, 576, 578, 578, 578, 578, 578, 578, 578, 578, 586, 587, - 588, 589, 530, 540, 541, 533, 534, 535, 536, 537, - 538, 539, 532, 825, 595, 542, 189, 189, 189, 189, - 189, 203, 1065, 341, 594, 706, 708, 709, 606, 737, - 707, 738, 431, 921, 628, 910, 623, 809, 621, 622, - 189, 739, 188, 188, 188, 188, 188, 1019, 341, 341, - 203, 1019, 1020, 982, 981, 902, 341, 1032, 188, 969, - 341, 631, 636, 642, 63, 63, 188, 490, 141, 522, - 607, 226, 596, 610, 638, 854, 341, 666, 667, 668, - 619, 608, 609, 221, 611, 928, 927, 556, 557, 558, - 559, 560, 561, 562, 630, 633, 210, 377, 629, 925, - 924, 1031, 235, 645, 634, 521, 751, 341, 679, 660, - 661, 662, 663, 579, 580, 581, 582, 583, 584, 585, - 45, 519, 518, 61, 670, 671, 672, 415, 341, 452, - 451, 918, 19, 748, 441, 675, 676, 63, 520, 881, - 19, 883, 141, 783, 443, 141, 141, 141, 141, 141, - 714, 204, 715, 443, 38, 777, 414, 141, 778, 854, - 783, 141, 751, 965, 19, 141, 1014, 415, 567, 141, - 141, 926, 623, 854, 752, 442, 750, 440, 41, 175, - 415, 63, 854, 802, 590, 415, 41, 763, 638, 533, - 534, 535, 536, 537, 538, 539, 532, 740, 741, 542, - 41, 681, 443, 659, 780, 781, 678, 896, 779, 805, - 41, 420, 423, 424, 425, 421, 765, 422, 426, 758, - 786, 787, 141, 602, 674, 41, 669, 141, 55, 130, - 141, 63, 793, 769, 912, 768, 883, 828, 789, 500, - 338, 17, 792, 791, 790, 237, 237, 237, 237, 616, - 237, 237, 642, 613, 617, 712, 612, 237, 721, 722, - 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, - 733, 734, 735, 816, 817, 803, 614, 799, 800, 702, - 182, 615, 618, 235, 424, 425, 1077, 807, 173, 179, - 180, 1073, 63, 204, 237, 840, 1072, 409, 774, 773, - 343, 235, 820, 448, 345, 403, 63, 821, 822, 823, - 237, 407, 344, 227, 811, 237, 1051, 1050, 1012, 806, - 963, 991, 683, 499, 237, 237, 237, 237, 237, 237, - 237, 237, 428, 176, 177, 409, 368, 367, 370, 371, - 372, 373, 714, 831, 715, 369, 374, 772, 851, 170, - 1042, 861, 852, 171, 844, 771, 45, 1041, 63, 1011, - 783, 1043, 863, 864, 986, 516, 868, 47, 49, 439, - 63, 874, 42, 875, 876, 877, 878, 1, 686, 888, - 1052, 38, 907, 647, 203, 889, 639, 208, 54, 753, - 754, 884, 646, 757, 824, 898, 899, 900, 893, 1026, - 984, 871, 653, 887, 813, 656, 901, 764, 911, 766, - 767, 63, 63, 904, 642, 903, 642, 892, 1048, 810, - 455, 456, 775, 454, 458, 457, 453, 151, 195, 427, - 63, 445, 237, 237, 855, 905, 680, 56, 833, 906, - 832, 684, 214, 550, 770, 196, 890, 591, 401, 845, - 846, 847, 1040, 1010, 870, 574, 759, 919, 920, 354, - 705, 366, 937, 363, 420, 423, 424, 425, 421, 365, - 422, 426, 750, 933, 786, 787, 364, 597, 63, 776, - 524, 523, 189, 352, 638, 957, 938, 939, 955, 954, - 942, 941, 931, 346, 187, 411, 419, 966, 967, 968, - 141, 971, 964, 962, 417, 598, 416, 192, 188, 788, - 63, 63, 204, 972, 566, 784, 978, 642, 186, 880, - 1007, 575, 1055, 980, 975, 976, 977, 961, 601, 20, - 235, 63, 63, 46, 63, 63, 181, 16, 15, 14, - 803, 204, 13, 24, 12, 11, 10, 9, 237, 237, - 8, 994, 995, 7, 6, 5, 4, 1006, 141, 983, - 172, 18, 141, 1004, 1005, 853, 888, 999, 63, 1016, - 2, 0, 0, 1015, 0, 0, 0, 0, 0, 869, - 935, 936, 1013, 635, 1021, 1022, 1023, 63, 1024, 0, - 887, 0, 1033, 1025, 996, 997, 0, 998, 0, 237, - 1000, 0, 1002, 0, 0, 904, 0, 0, 0, 0, - 1035, 141, 0, 0, 0, 888, 1038, 38, 378, 0, - 0, 1045, 1044, 0, 0, 0, 63, 0, 63, 63, - 63, 141, 63, 0, 0, 63, 234, 0, 0, 887, - 0, 0, 0, 0, 0, 0, 1059, 0, 139, 0, - 203, 162, 703, 704, 1061, 710, 711, 1060, 0, 63, - 742, 1064, 237, 0, 1067, 992, 0, 0, 1071, 0, - 139, 139, 205, 0, 762, 0, 139, 0, 0, 1080, - 0, 540, 541, 533, 534, 535, 536, 537, 538, 539, - 532, 1085, 1086, 542, 0, 0, 0, 0, 0, 63, - 63, 566, 0, 0, 755, 756, 0, 0, 0, 0, - 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 63, 403, 0, 798, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1037, 237, 0, - 0, 0, 0, 934, 0, 0, 0, 0, 0, 63, - 139, 0, 139, 0, 0, 0, 139, 0, 0, 0, - 0, 0, 139, 531, 530, 540, 541, 533, 534, 535, - 536, 537, 538, 539, 532, 0, 63, 542, 0, 829, - 237, 0, 0, 0, 63, 331, 332, 333, 0, 336, - 337, 0, 0, 0, 0, 850, 339, 190, 237, 0, - 0, 139, 0, 0, 0, 0, 0, 0, 139, 436, - 139, 1082, 0, 0, 205, 531, 530, 540, 541, 533, - 534, 535, 536, 537, 538, 539, 532, 138, 0, 542, - 0, 0, 0, 139, 0, 139, 0, 0, 139, 0, - 0, 139, 0, 503, 0, 0, 858, 0, 0, 491, - 193, 0, 0, 0, 496, 212, 0, 0, 0, 0, - 0, 0, 0, 505, 506, 507, 508, 509, 510, 511, - 512, 0, 0, 0, 0, 204, 0, 0, 891, 798, - 0, 0, 0, 0, 0, 862, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 873, 0, 0, 0, 237, - 237, 0, 237, 909, 531, 530, 540, 541, 533, 534, - 535, 536, 537, 538, 539, 532, 0, 894, 542, 0, - 895, 0, 0, 897, 0, 0, 0, 0, 0, 217, - 0, 218, 0, 0, 0, 223, 932, 0, 0, 0, - 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 858, 0, 139, 237, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 513, 514, 0, 0, 0, 0, 0, 0, 0, - 413, 0, 0, 0, 0, 0, 0, 0, 0, 438, - 0, 0, 0, 0, 974, 0, 974, 974, 974, 0, - 979, 0, 0, 237, 0, 0, 959, 0, 0, 0, - 0, 0, 493, 0, 495, 0, 0, 498, 0, 0, - 501, 0, 566, 0, 0, 0, 0, 237, 0, 0, - 0, 139, 0, 205, 139, 139, 139, 139, 139, 0, - 0, 0, 0, 0, 0, 0, 620, 0, 0, 0, - 139, 0, 0, 0, 436, 0, 0, 0, 139, 139, - 0, 0, 205, 0, 0, 0, 0, 1017, 1018, 503, + 588, 589, 1019, 341, 341, 519, 518, 519, 518, 706, + 708, 709, 960, 490, 707, 594, 191, 191, 191, 191, + 191, 606, 520, 228, 520, 223, 595, 212, 592, 593, + 1019, 1020, 431, 1032, 628, 1031, 205, 841, 842, 843, + 191, 143, 918, 143, 623, 982, 981, 143, 902, 341, + 621, 622, 19, 143, 443, 631, 751, 63, 63, 63, + 63, 965, 63, 63, 596, 205, 969, 341, 415, 63, + 666, 667, 668, 926, 519, 518, 638, 377, 1014, 556, + 557, 558, 559, 560, 561, 562, 629, 630, 619, 634, + 552, 520, 143, 633, 854, 341, 636, 642, 41, 143, + 143, 143, 237, 61, 928, 927, 63, 645, 679, 608, + 609, 607, 611, 854, 610, 579, 580, 581, 582, 583, + 584, 585, 63, 802, 143, 522, 143, 63, 590, 143, + 19, 206, 143, 701, 143, 867, 63, 63, 63, 63, + 63, 63, 63, 63, 881, 714, 675, 676, 925, 924, + 660, 661, 662, 663, 38, 190, 190, 190, 190, 190, + 441, 521, 19, 751, 341, 670, 671, 672, 567, 415, + 341, 190, 452, 451, 45, 783, 41, 519, 518, 190, + 623, 783, 414, 519, 518, 777, 752, 854, 778, 883, + 638, 681, 443, 41, 520, 177, 659, 740, 741, 763, + 520, 442, 912, 440, 780, 781, 415, 678, 41, 896, + 750, 805, 883, 854, 765, 674, 779, 415, 758, 786, + 787, 828, 17, 443, 669, 55, 132, 239, 239, 239, + 239, 789, 239, 239, 500, 769, 338, 768, 602, 239, + 616, 41, 63, 63, 793, 617, 143, 712, 792, 790, + 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, + 731, 732, 733, 734, 735, 715, 816, 817, 803, 175, + 791, 613, 799, 800, 612, 206, 239, 184, 420, 423, + 424, 425, 421, 237, 422, 426, 642, 807, 786, 787, + 614, 618, 239, 424, 425, 615, 1077, 239, 181, 182, + 1073, 237, 821, 822, 823, 840, 239, 239, 239, 239, + 239, 239, 239, 239, 830, 63, 702, 409, 1072, 774, + 143, 773, 343, 143, 143, 143, 143, 143, 831, 820, + 448, 407, 839, 811, 344, 143, 229, 714, 1051, 143, + 1050, 1012, 806, 143, 963, 991, 683, 143, 143, 753, + 754, 861, 499, 757, 844, 428, 178, 179, 409, 63, + 851, 172, 1042, 772, 852, 173, 45, 764, 1041, 766, + 767, 771, 1011, 783, 863, 864, 47, 1043, 868, 888, + 986, 38, 775, 874, 884, 875, 876, 877, 878, 516, + 49, 439, 42, 889, 871, 898, 899, 900, 887, 205, + 143, 1, 686, 1052, 907, 143, 893, 647, 143, 63, + 639, 210, 239, 239, 54, 892, 646, 824, 901, 1026, + 984, 653, 813, 903, 420, 423, 424, 425, 421, 656, + 422, 426, 906, 911, 1048, 905, 810, 455, 934, 456, + 454, 845, 846, 847, 458, 457, 748, 904, 642, 453, + 642, 153, 919, 920, 197, 427, 445, 715, 531, 530, + 540, 541, 533, 534, 535, 536, 537, 538, 539, 532, + 63, 855, 542, 680, 937, 56, 933, 931, 833, 938, + 832, 954, 191, 684, 63, 598, 638, 939, 942, 941, + 955, 216, 206, 957, 550, 770, 964, 962, 368, 367, + 370, 371, 372, 373, 972, 198, 750, 369, 374, 966, + 967, 968, 890, 971, 980, 975, 976, 977, 591, 978, + 401, 206, 961, 1040, 1010, 853, 870, 574, 239, 239, + 237, 759, 354, 803, 705, 366, 63, 363, 365, 869, + 364, 597, 776, 524, 352, 346, 189, 411, 63, 419, + 417, 642, 416, 194, 788, 784, 188, 1006, 880, 1007, + 1055, 990, 601, 994, 995, 20, 888, 999, 46, 1016, + 183, 16, 935, 936, 1013, 1004, 1005, 15, 14, 239, + 13, 1015, 24, 12, 11, 887, 10, 1025, 1024, 63, + 63, 9, 1033, 8, 7, 6, 1021, 1022, 1023, 5, + 983, 4, 174, 1035, 18, 2, 0, 0, 63, 0, + 0, 0, 0, 0, 0, 888, 0, 38, 0, 345, + 403, 190, 1044, 0, 0, 0, 0, 0, 1038, 1045, + 0, 0, 0, 0, 887, 996, 997, 0, 998, 904, + 742, 1000, 239, 1002, 0, 0, 1059, 0, 0, 0, + 1060, 0, 0, 0, 762, 0, 63, 992, 0, 0, + 0, 0, 0, 0, 0, 205, 1061, 0, 1071, 0, + 0, 850, 0, 1064, 0, 0, 1067, 0, 143, 1080, + 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, + 0, 531, 530, 540, 541, 533, 534, 535, 536, 537, + 538, 539, 532, 1085, 1086, 542, 798, 0, 0, 63, + 63, 0, 63, 63, 192, 0, 0, 0, 239, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 378, 1037, + 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, + 143, 0, 0, 0, 140, 0, 63, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 829, + 239, 164, 0, 0, 0, 63, 0, 195, 0, 0, + 0, 0, 214, 0, 0, 0, 0, 0, 239, 0, + 141, 141, 207, 0, 0, 0, 141, 0, 0, 143, + 0, 0, 0, 0, 523, 0, 0, 0, 0, 0, + 0, 0, 0, 1082, 63, 0, 63, 63, 63, 143, + 63, 0, 0, 63, 531, 530, 540, 541, 533, 534, + 535, 536, 537, 538, 539, 532, 858, 566, 542, 0, + 0, 0, 0, 0, 575, 0, 0, 63, 0, 0, + 0, 0, 0, 151, 0, 0, 0, 0, 219, 0, + 220, 0, 0, 0, 225, 206, 0, 0, 891, 798, + 227, 0, 141, 0, 141, 0, 0, 161, 141, 0, + 0, 0, 0, 0, 141, 0, 0, 63, 63, 239, + 239, 0, 239, 909, 0, 0, 0, 0, 0, 0, + 63, 0, 0, 0, 0, 0, 635, 0, 0, 413, + 0, 63, 0, 0, 0, 0, 0, 0, 438, 0, + 0, 0, 0, 141, 0, 0, 932, 146, 0, 0, + 141, 436, 141, 148, 0, 0, 207, 63, 154, 150, + 0, 493, 0, 495, 0, 858, 498, 0, 239, 501, + 0, 0, 0, 0, 0, 141, 0, 141, 0, 152, + 141, 0, 156, 141, 63, 503, 0, 0, 0, 0, + 0, 0, 63, 0, 0, 703, 704, 0, 710, 711, + 0, 0, 0, 0, 974, 147, 974, 974, 974, 0, + 979, 0, 0, 239, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 155, 157, 158, 159, 160, + 0, 0, 163, 162, 0, 0, 0, 239, 0, 0, + 0, 0, 0, 0, 566, 0, 0, 755, 756, 530, + 540, 541, 533, 534, 535, 536, 537, 538, 539, 532, + 0, 0, 542, 0, 0, 0, 0, 403, 0, 461, + 0, 0, 0, 0, 0, 0, 0, 1017, 1018, 0, + 0, 0, 0, 515, 0, 0, 0, 0, 0, 0, + 909, 473, 0, 0, 0, 0, 0, 141, 0, 0, + 0, 239, 0, 0, 0, 0, 0, 478, 479, 480, + 481, 482, 483, 484, 0, 485, 486, 487, 488, 489, + 474, 475, 476, 477, 459, 460, 0, 1047, 462, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 909, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 237, 0, 0, 1009, 0, 0, 0, 0, 0, + 0, 206, 0, 0, 1062, 0, 0, 605, 0, 0, + 0, 0, 1066, 0, 0, 0, 0, 0, 0, 0, + 0, 141, 0, 207, 141, 141, 141, 141, 141, 0, + 0, 0, 0, 0, 0, 632, 620, 0, 0, 0, + 141, 0, 0, 0, 436, 0, 0, 0, 141, 141, + 0, 0, 207, 0, 0, 0, 0, 0, 0, 503, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 139, 0, 97, 0, 0, 139, 1047, 0, 139, - 0, 0, 77, 0, 0, 0, 0, 84, 0, 86, - 0, 0, 106, 93, 0, 0, 515, 0, 701, 0, - 0, 204, 0, 0, 1062, 0, 0, 0, 0, 0, - 0, 62, 1066, 0, 0, 0, 0, 0, 0, 0, - 72, 0, 0, 0, 0, 58, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1058, 566, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 862, 0, + 0, 0, 0, 0, 0, 0, 0, 682, 873, 0, + 0, 0, 699, 0, 0, 700, 0, 0, 0, 0, + 0, 141, 0, 0, 0, 0, 141, 0, 0, 141, + 894, 97, 0, 895, 0, 857, 897, 0, 0, 0, + 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, + 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, + 0, 859, 0, 0, 0, 0, 0, 0, 72, 0, + 0, 0, 0, 519, 518, 0, 0, 0, 0, 0, 0, 0, 749, 503, 0, 0, 0, 749, 749, 0, - 0, 749, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 749, 749, 749, 749, 0, - 605, 0, 59, 0, 57, 0, 0, 0, 60, 100, - 749, 0, 0, 73, 0, 105, 98, 0, 0, 99, - 104, 87, 110, 101, 116, 121, 122, 0, 632, 66, - 114, 108, 91, 81, 82, 65, 0, 103, 76, 80, - 75, 96, 111, 112, 74, 128, 69, 120, 68, 70, - 119, 95, 109, 115, 92, 89, 67, 113, 90, 88, - 83, 78, 0, 0, 0, 107, 117, 129, 0, 0, - 123, 124, 125, 126, 94, 71, 0, 0, 0, 0, - 682, 0, 0, 0, 0, 699, 0, 0, 700, 19, - 39, 21, 22, 64, 0, 85, 127, 102, 79, 118, - 0, 0, 0, 0, 0, 0, 0, 33, 0, 830, - 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 839, 0, 0, - 0, 32, 0, 0, 0, 41, 0, 0, 0, 0, + 520, 749, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 749, 749, 749, 749, 959, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 749, 0, 144, 0, 0, 566, 0, 100, 0, 0, + 0, 73, 0, 105, 98, 0, 0, 99, 104, 87, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, + 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 0, 0, 107, 118, 131, 0, 0, 125, 126, + 127, 128, 94, 71, 0, 0, 0, 1009, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 526, 64, 529, 85, 129, 102, 79, 119, 543, 544, + 545, 546, 547, 548, 549, 0, 527, 528, 525, 531, + 530, 540, 541, 533, 534, 535, 536, 537, 538, 539, + 532, 0, 0, 542, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 749, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 749, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, - 0, 0, 0, 0, 0, 0, 205, 0, 0, 0, - 0, 0, 0, 0, 25, 26, 28, 27, 30, 0, - 0, 0, 0, 0, 0, 0, 0, 31, 34, 35, - 0, 0, 36, 37, 29, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 879, 0, 749, 1058, 566, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 141, + 0, 0, 0, 0, 0, 0, 207, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 929, 0, 0, 0, 930, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 141, 0, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 139, 0, 0, - 0, 139, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 749, 0, 0, 0, 0, 0, 503, - 749, 0, 0, 0, 0, 473, 0, 0, 0, 0, - 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, - 139, 478, 479, 480, 481, 482, 483, 484, 0, 485, - 486, 487, 488, 489, 474, 475, 476, 477, 459, 460, - 436, 0, 462, 0, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 526, 0, 529, 0, 0, 0, - 0, 0, 543, 544, 545, 546, 547, 548, 549, 0, - 527, 528, 525, 531, 530, 540, 541, 533, 534, 535, - 536, 537, 538, 539, 532, 0, 990, 542, 879, 0, - 319, 307, 280, 321, 257, 271, 330, 273, 274, 301, - 245, 288, 97, 269, 0, 260, 240, 266, 241, 258, - 282, 77, 285, 256, 310, 291, 84, 327, 86, 296, - 0, 106, 93, 0, 0, 284, 312, 286, 306, 279, - 302, 250, 295, 322, 270, 299, 323, 0, 0, 0, - 62, 0, 643, 644, 0, 0, 929, 0, 0, 72, - 930, 298, 318, 268, 300, 239, 297, 0, 243, 246, - 329, 316, 263, 264, 804, 0, 0, 0, 0, 0, - 0, 283, 287, 303, 277, 0, 0, 0, 0, 0, - 0, 0, 205, 261, 0, 294, 0, 0, 0, 247, - 244, 0, 281, 0, 0, 0, 249, 0, 262, 304, - 0, 314, 278, 142, 317, 276, 275, 320, 100, 311, - 259, 267, 73, 265, 105, 98, 0, 293, 99, 104, - 87, 110, 101, 116, 121, 122, 313, 328, 66, 114, - 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, - 96, 111, 112, 74, 128, 69, 120, 68, 70, 119, - 95, 109, 115, 92, 89, 67, 113, 90, 88, 83, - 78, 0, 242, 0, 107, 117, 129, 255, 315, 123, - 124, 125, 126, 94, 71, 272, 309, 253, 254, 251, - 252, 289, 290, 324, 325, 326, 305, 248, 0, 0, - 308, 292, 64, 0, 85, 127, 102, 79, 118, 319, - 307, 280, 321, 257, 271, 330, 273, 274, 301, 245, - 288, 97, 269, 0, 260, 240, 266, 241, 258, 282, - 77, 285, 256, 310, 291, 84, 327, 86, 296, 0, - 106, 93, 0, 0, 284, 312, 286, 306, 279, 302, - 250, 295, 322, 270, 299, 323, 0, 0, 0, 62, - 0, 643, 644, 0, 0, 0, 0, 0, 72, 0, - 298, 318, 268, 300, 239, 297, 0, 243, 246, 329, - 316, 263, 264, 0, 0, 0, 0, 0, 0, 0, - 283, 287, 303, 277, 0, 0, 0, 0, 0, 0, - 0, 0, 261, 0, 294, 0, 0, 0, 247, 244, - 0, 281, 0, 0, 0, 249, 0, 262, 304, 0, - 314, 278, 142, 317, 276, 275, 320, 100, 311, 259, - 267, 73, 265, 105, 98, 0, 293, 99, 104, 87, - 110, 101, 116, 121, 122, 313, 328, 66, 114, 108, - 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, - 111, 112, 74, 128, 69, 120, 68, 70, 119, 95, - 109, 115, 92, 89, 67, 113, 90, 88, 83, 78, - 0, 242, 0, 107, 117, 129, 255, 315, 123, 124, - 125, 126, 94, 71, 272, 309, 253, 254, 251, 252, - 289, 290, 324, 325, 326, 305, 248, 0, 0, 308, - 292, 64, 0, 85, 127, 102, 79, 118, 319, 307, - 280, 321, 257, 271, 330, 273, 274, 301, 245, 288, - 97, 269, 0, 260, 240, 266, 241, 258, 282, 77, - 285, 256, 310, 291, 84, 327, 86, 296, 0, 106, - 93, 0, 0, 284, 312, 286, 306, 279, 302, 250, - 295, 322, 270, 299, 323, 0, 0, 0, 62, 0, - 0, 0, 0, 0, 0, 0, 0, 72, 0, 298, - 318, 268, 300, 239, 297, 0, 243, 246, 329, 316, - 263, 264, 0, 0, 0, 0, 0, 0, 0, 283, - 287, 303, 277, 0, 0, 0, 0, 0, 0, 1034, - 0, 261, 0, 294, 0, 0, 0, 247, 244, 0, - 281, 0, 0, 0, 249, 0, 262, 304, 0, 314, - 278, 142, 317, 276, 275, 320, 100, 311, 259, 267, - 73, 265, 105, 98, 0, 293, 99, 104, 87, 110, - 101, 116, 121, 122, 313, 328, 66, 114, 108, 91, - 81, 82, 65, 0, 103, 76, 80, 75, 96, 111, - 112, 74, 128, 69, 120, 68, 70, 119, 95, 109, - 115, 92, 89, 67, 113, 90, 88, 83, 78, 0, - 242, 0, 107, 117, 129, 255, 315, 123, 124, 125, - 126, 94, 71, 272, 309, 253, 254, 251, 252, 289, - 290, 324, 325, 326, 305, 248, 0, 0, 308, 292, - 64, 0, 85, 127, 102, 79, 118, 319, 307, 280, - 321, 257, 271, 330, 273, 274, 301, 245, 288, 97, - 269, 0, 260, 240, 266, 241, 258, 282, 77, 285, - 256, 310, 291, 84, 327, 86, 296, 0, 106, 93, - 0, 0, 284, 312, 286, 306, 279, 302, 250, 295, - 322, 270, 299, 323, 41, 0, 0, 62, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 0, 298, 318, - 268, 300, 239, 297, 0, 243, 246, 329, 316, 263, - 264, 0, 0, 0, 0, 0, 0, 0, 283, 287, - 303, 277, 0, 0, 0, 0, 0, 0, 0, 0, - 261, 0, 294, 0, 0, 0, 247, 244, 0, 281, - 0, 0, 0, 249, 0, 262, 304, 0, 314, 278, - 142, 317, 276, 275, 320, 100, 311, 259, 267, 73, - 265, 105, 98, 0, 293, 99, 104, 87, 110, 101, - 116, 121, 122, 313, 328, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 242, - 0, 107, 117, 129, 255, 315, 123, 124, 125, 126, - 94, 71, 272, 309, 253, 254, 251, 252, 289, 290, - 324, 325, 326, 305, 248, 0, 0, 308, 292, 64, - 0, 85, 127, 102, 79, 118, 319, 307, 280, 321, - 257, 271, 330, 273, 274, 301, 245, 288, 97, 269, - 0, 260, 240, 266, 241, 258, 282, 77, 285, 256, - 310, 291, 84, 327, 86, 296, 0, 106, 93, 0, - 0, 284, 312, 286, 306, 279, 302, 250, 295, 322, - 270, 299, 323, 0, 0, 0, 206, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 298, 318, 268, - 300, 239, 297, 0, 243, 246, 329, 316, 263, 264, - 0, 0, 0, 0, 0, 0, 0, 283, 287, 303, - 277, 0, 0, 0, 0, 0, 0, 940, 0, 261, - 0, 294, 0, 0, 0, 247, 244, 0, 281, 0, - 0, 0, 249, 0, 262, 304, 0, 314, 278, 142, - 317, 276, 275, 320, 100, 311, 259, 267, 73, 265, - 105, 98, 0, 293, 99, 104, 87, 110, 101, 116, - 121, 122, 313, 328, 66, 114, 108, 91, 81, 82, - 65, 0, 103, 76, 80, 75, 96, 111, 112, 74, - 128, 69, 120, 68, 70, 119, 95, 109, 115, 92, - 89, 67, 113, 90, 88, 83, 78, 0, 242, 0, - 107, 117, 129, 255, 315, 123, 124, 125, 126, 94, - 71, 272, 309, 253, 254, 251, 252, 289, 290, 324, - 325, 326, 305, 248, 0, 0, 308, 292, 64, 0, - 85, 127, 102, 79, 118, 319, 307, 280, 321, 257, - 271, 330, 273, 274, 301, 245, 288, 97, 269, 0, - 260, 240, 266, 241, 258, 282, 77, 285, 256, 310, - 291, 84, 327, 86, 296, 0, 106, 93, 0, 0, - 284, 312, 286, 306, 279, 302, 250, 295, 322, 270, - 299, 323, 0, 0, 0, 62, 0, 447, 0, 0, - 0, 0, 0, 0, 72, 0, 298, 318, 268, 300, - 239, 297, 0, 243, 246, 329, 316, 263, 264, 0, - 0, 0, 0, 0, 0, 0, 283, 287, 303, 277, - 0, 0, 0, 0, 0, 0, 0, 0, 261, 0, - 294, 0, 0, 0, 247, 244, 0, 281, 0, 0, - 0, 249, 0, 262, 304, 0, 314, 278, 142, 317, - 276, 275, 320, 100, 311, 259, 267, 73, 265, 105, - 98, 0, 293, 99, 104, 87, 110, 101, 116, 121, - 122, 313, 328, 66, 114, 108, 91, 81, 82, 65, - 0, 103, 76, 80, 75, 96, 111, 112, 74, 128, - 69, 120, 68, 70, 119, 95, 109, 115, 92, 89, - 67, 113, 90, 88, 83, 78, 0, 242, 0, 107, - 117, 129, 255, 315, 123, 124, 125, 126, 94, 71, - 272, 309, 253, 254, 251, 252, 289, 290, 324, 325, - 326, 305, 248, 0, 0, 308, 292, 64, 0, 85, - 127, 102, 79, 118, 319, 307, 280, 321, 257, 271, - 330, 273, 274, 301, 245, 288, 97, 269, 0, 260, - 240, 266, 241, 258, 282, 77, 285, 256, 310, 291, - 84, 327, 86, 296, 0, 106, 93, 0, 0, 284, - 312, 286, 306, 279, 302, 250, 295, 322, 270, 299, - 323, 0, 0, 0, 62, 0, 0, 0, 0, 0, - 0, 0, 0, 72, 0, 298, 318, 268, 300, 239, - 297, 0, 243, 246, 329, 316, 263, 264, 0, 0, - 0, 0, 0, 0, 0, 283, 287, 303, 277, 0, - 0, 0, 0, 0, 0, 0, 0, 261, 0, 294, - 0, 0, 0, 247, 244, 0, 281, 0, 0, 0, - 249, 0, 262, 304, 0, 314, 278, 142, 317, 276, - 275, 320, 100, 311, 259, 267, 73, 265, 105, 98, - 0, 293, 99, 104, 87, 110, 101, 116, 121, 122, - 313, 328, 66, 114, 108, 91, 81, 82, 65, 0, - 103, 76, 80, 75, 96, 111, 112, 74, 128, 69, - 120, 68, 70, 119, 95, 109, 115, 92, 89, 67, - 113, 90, 88, 83, 78, 0, 242, 0, 107, 117, - 129, 255, 315, 123, 124, 125, 126, 94, 71, 272, - 309, 253, 254, 251, 252, 289, 290, 324, 325, 326, - 305, 248, 0, 0, 308, 292, 64, 0, 85, 127, - 102, 79, 118, 319, 307, 280, 321, 257, 271, 330, - 273, 274, 301, 245, 288, 97, 269, 0, 260, 240, - 266, 241, 258, 282, 77, 285, 256, 310, 291, 84, - 327, 86, 296, 0, 106, 93, 0, 0, 284, 312, - 286, 306, 279, 302, 250, 295, 322, 270, 299, 323, - 0, 0, 0, 206, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 298, 318, 268, 300, 239, 297, - 0, 243, 246, 329, 316, 263, 264, 0, 0, 0, - 0, 0, 0, 0, 283, 287, 303, 277, 0, 0, - 0, 0, 0, 0, 0, 0, 261, 0, 294, 0, - 0, 0, 247, 244, 0, 281, 0, 0, 0, 249, - 0, 262, 304, 0, 314, 278, 142, 317, 276, 275, - 320, 100, 311, 259, 267, 73, 265, 105, 98, 0, - 293, 99, 104, 87, 110, 101, 116, 121, 122, 313, - 328, 66, 114, 108, 91, 81, 82, 65, 0, 103, - 76, 80, 75, 96, 111, 112, 74, 128, 69, 120, - 68, 70, 119, 95, 109, 115, 92, 89, 67, 113, - 90, 88, 83, 78, 0, 242, 0, 107, 117, 129, - 255, 315, 123, 124, 125, 126, 94, 71, 272, 309, - 253, 254, 251, 252, 289, 290, 324, 325, 326, 305, - 248, 0, 0, 308, 292, 64, 0, 85, 127, 102, - 79, 118, 319, 307, 280, 321, 257, 271, 330, 273, - 274, 301, 245, 288, 97, 269, 0, 260, 240, 266, - 241, 258, 282, 77, 285, 256, 310, 291, 84, 327, - 86, 296, 0, 106, 93, 0, 0, 284, 312, 286, - 306, 279, 302, 250, 295, 322, 270, 299, 323, 0, - 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, - 0, 72, 0, 298, 318, 268, 300, 239, 297, 0, - 243, 246, 329, 316, 263, 264, 0, 0, 0, 0, - 0, 0, 0, 283, 287, 303, 277, 0, 0, 0, - 0, 0, 0, 0, 0, 261, 0, 294, 0, 0, - 0, 247, 244, 0, 281, 0, 0, 0, 249, 0, - 262, 304, 0, 314, 278, 142, 317, 276, 275, 320, - 100, 311, 259, 267, 73, 265, 105, 98, 0, 293, - 99, 104, 87, 110, 101, 116, 121, 122, 313, 328, - 66, 114, 108, 91, 81, 82, 65, 0, 103, 76, - 80, 75, 96, 111, 112, 74, 128, 69, 120, 68, - 70, 119, 95, 109, 115, 92, 89, 67, 113, 90, - 88, 83, 78, 0, 242, 0, 107, 117, 129, 255, - 315, 123, 124, 125, 126, 94, 71, 272, 309, 253, - 254, 251, 252, 289, 290, 324, 325, 326, 305, 248, - 0, 0, 308, 292, 64, 0, 85, 127, 102, 79, - 118, 97, 0, 0, 744, 0, 350, 0, 0, 0, - 77, 0, 349, 0, 0, 84, 388, 86, 0, 0, - 106, 93, 0, 0, 0, 0, 381, 382, 0, 0, - 0, 0, 0, 0, 0, 0, 41, 0, 0, 206, - 368, 367, 370, 371, 372, 373, 0, 0, 72, 369, - 374, 375, 376, 0, 0, 347, 361, 0, 387, 0, + 749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 358, 359, - 747, 0, 0, 0, 399, 0, 360, 0, 0, 356, - 357, 362, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 0, 0, 397, 0, 100, 0, 0, - 0, 73, 0, 105, 98, 0, 0, 99, 104, 87, - 110, 101, 116, 121, 122, 0, 0, 66, 114, 108, - 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, - 111, 112, 74, 128, 69, 120, 68, 70, 119, 95, - 109, 115, 92, 89, 67, 113, 90, 88, 83, 78, - 0, 0, 0, 107, 117, 129, 0, 0, 123, 124, - 125, 126, 94, 71, 0, 0, 389, 398, 395, 396, - 393, 394, 392, 391, 390, 400, 383, 384, 386, 0, - 385, 64, 0, 85, 127, 102, 79, 118, 97, 0, - 0, 0, 0, 350, 0, 0, 0, 77, 0, 349, - 0, 0, 84, 388, 86, 0, 0, 106, 93, 0, - 0, 0, 0, 381, 382, 0, 0, 0, 0, 0, - 0, 0, 0, 41, 0, 341, 206, 368, 367, 370, - 371, 372, 373, 0, 0, 72, 369, 374, 375, 376, - 0, 0, 347, 361, 0, 387, 0, 0, 0, 0, + 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 358, 359, 0, 0, 0, - 0, 399, 0, 360, 0, 0, 356, 357, 362, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 0, 0, 397, 0, 100, 0, 0, 0, 73, 0, - 105, 98, 0, 0, 99, 104, 87, 110, 101, 116, - 121, 122, 0, 0, 66, 114, 108, 91, 81, 82, - 65, 0, 103, 76, 80, 75, 96, 111, 112, 74, - 128, 69, 120, 68, 70, 119, 95, 109, 115, 92, - 89, 67, 113, 90, 88, 83, 78, 0, 0, 0, - 107, 117, 129, 0, 0, 123, 124, 125, 126, 94, - 71, 0, 0, 389, 398, 395, 396, 393, 394, 392, - 391, 390, 400, 383, 384, 386, 0, 385, 64, 0, - 85, 127, 102, 79, 118, 97, 0, 0, 0, 0, - 350, 0, 0, 0, 77, 0, 349, 0, 0, 84, - 388, 86, 0, 0, 106, 93, 0, 0, 0, 0, - 381, 382, 0, 0, 0, 0, 0, 0, 0, 0, - 41, 0, 0, 206, 368, 367, 370, 371, 372, 373, - 0, 0, 72, 369, 374, 375, 376, 0, 0, 347, - 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, + 436, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 320, 309, 282, 322, + 259, 273, 330, 275, 276, 303, 247, 290, 97, 271, + 0, 262, 242, 268, 243, 260, 284, 77, 287, 258, + 312, 293, 84, 328, 86, 298, 0, 106, 93, 0, + 0, 286, 314, 288, 308, 281, 304, 252, 297, 323, + 272, 301, 324, 0, 0, 0, 62, 0, 643, 644, + 0, 0, 0, 0, 0, 72, 0, 300, 319, 270, + 302, 241, 299, 0, 245, 248, 329, 317, 265, 266, + 804, 0, 0, 0, 0, 0, 0, 285, 289, 305, + 279, 0, 0, 0, 0, 0, 0, 0, 0, 263, + 0, 296, 0, 0, 0, 249, 246, 0, 283, 0, + 0, 0, 251, 0, 264, 306, 0, 315, 280, 144, + 318, 278, 277, 321, 100, 313, 261, 269, 73, 267, + 105, 98, 207, 295, 99, 104, 87, 111, 101, 117, + 123, 124, 109, 122, 66, 115, 108, 91, 81, 82, + 65, 0, 103, 76, 80, 75, 96, 112, 113, 74, + 130, 69, 121, 68, 70, 120, 95, 110, 116, 92, + 89, 67, 114, 90, 88, 83, 78, 0, 244, 0, + 107, 118, 131, 257, 316, 125, 126, 127, 128, 94, + 71, 274, 311, 255, 256, 253, 254, 291, 292, 325, + 326, 327, 307, 250, 0, 0, 310, 294, 64, 0, + 85, 129, 102, 79, 119, 320, 309, 282, 322, 259, + 273, 330, 275, 276, 303, 247, 290, 97, 271, 0, + 262, 242, 268, 243, 260, 284, 77, 287, 258, 312, + 293, 84, 328, 86, 298, 0, 106, 93, 0, 0, + 286, 314, 288, 308, 281, 304, 252, 297, 323, 272, + 301, 324, 0, 0, 0, 62, 0, 643, 644, 0, + 0, 0, 0, 0, 72, 0, 300, 319, 270, 302, + 241, 299, 0, 245, 248, 329, 317, 265, 266, 0, + 0, 0, 0, 0, 0, 0, 285, 289, 305, 279, + 0, 0, 0, 0, 0, 0, 0, 0, 263, 0, + 296, 0, 0, 0, 249, 246, 0, 283, 0, 0, + 0, 251, 0, 264, 306, 0, 315, 280, 144, 318, + 278, 277, 321, 100, 313, 261, 269, 73, 267, 105, + 98, 0, 295, 99, 104, 87, 111, 101, 117, 123, + 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, + 0, 103, 76, 80, 75, 96, 112, 113, 74, 130, + 69, 121, 68, 70, 120, 95, 110, 116, 92, 89, + 67, 114, 90, 88, 83, 78, 0, 244, 0, 107, + 118, 131, 257, 316, 125, 126, 127, 128, 94, 71, + 274, 311, 255, 256, 253, 254, 291, 292, 325, 326, + 327, 307, 250, 0, 0, 310, 294, 64, 0, 85, + 129, 102, 79, 119, 320, 309, 282, 322, 259, 273, + 330, 275, 276, 303, 247, 290, 97, 271, 0, 262, + 242, 268, 243, 260, 284, 77, 287, 258, 312, 293, + 84, 328, 86, 298, 0, 106, 93, 0, 0, 286, + 314, 288, 308, 281, 304, 252, 297, 323, 272, 301, + 324, 0, 0, 0, 62, 0, 0, 0, 0, 0, + 0, 0, 0, 72, 0, 300, 319, 270, 302, 241, + 299, 0, 245, 248, 329, 317, 265, 266, 0, 0, + 0, 0, 0, 0, 0, 285, 289, 305, 279, 0, + 0, 0, 0, 0, 0, 1034, 0, 263, 0, 296, + 0, 0, 0, 249, 246, 0, 283, 0, 0, 0, + 251, 0, 264, 306, 0, 315, 280, 144, 318, 278, + 277, 321, 100, 313, 261, 269, 73, 267, 105, 98, + 0, 295, 99, 104, 87, 111, 101, 117, 123, 124, + 109, 122, 66, 115, 108, 91, 81, 82, 65, 0, + 103, 76, 80, 75, 96, 112, 113, 74, 130, 69, + 121, 68, 70, 120, 95, 110, 116, 92, 89, 67, + 114, 90, 88, 83, 78, 0, 244, 0, 107, 118, + 131, 257, 316, 125, 126, 127, 128, 94, 71, 274, + 311, 255, 256, 253, 254, 291, 292, 325, 326, 327, + 307, 250, 0, 0, 310, 294, 64, 0, 85, 129, + 102, 79, 119, 320, 309, 282, 322, 259, 273, 330, + 275, 276, 303, 247, 290, 97, 271, 0, 262, 242, + 268, 243, 260, 284, 77, 287, 258, 312, 293, 84, + 328, 86, 298, 0, 106, 93, 0, 0, 286, 314, + 288, 308, 281, 304, 252, 297, 323, 272, 301, 324, + 41, 0, 0, 62, 0, 0, 0, 0, 0, 0, + 0, 0, 72, 0, 300, 319, 270, 302, 241, 299, + 0, 245, 248, 329, 317, 265, 266, 0, 0, 0, + 0, 0, 0, 0, 285, 289, 305, 279, 0, 0, + 0, 0, 0, 0, 0, 0, 263, 0, 296, 0, + 0, 0, 249, 246, 0, 283, 0, 0, 0, 251, + 0, 264, 306, 0, 315, 280, 144, 318, 278, 277, + 321, 100, 313, 261, 269, 73, 267, 105, 98, 0, + 295, 99, 104, 87, 111, 101, 117, 123, 124, 109, + 122, 66, 115, 108, 91, 81, 82, 65, 0, 103, + 76, 80, 75, 96, 112, 113, 74, 130, 69, 121, + 68, 70, 120, 95, 110, 116, 92, 89, 67, 114, + 90, 88, 83, 78, 0, 244, 0, 107, 118, 131, + 257, 316, 125, 126, 127, 128, 94, 71, 274, 311, + 255, 256, 253, 254, 291, 292, 325, 326, 327, 307, + 250, 0, 0, 310, 294, 64, 0, 85, 129, 102, + 79, 119, 320, 309, 282, 322, 259, 273, 330, 275, + 276, 303, 247, 290, 97, 271, 0, 262, 242, 268, + 243, 260, 284, 77, 287, 258, 312, 293, 84, 328, + 86, 298, 0, 106, 93, 0, 0, 286, 314, 288, + 308, 281, 304, 252, 297, 323, 272, 301, 324, 0, + 0, 0, 208, 0, 0, 0, 0, 0, 0, 0, + 0, 72, 0, 300, 319, 270, 302, 241, 299, 0, + 245, 248, 329, 317, 265, 266, 0, 0, 0, 0, + 0, 0, 0, 285, 289, 305, 279, 0, 0, 0, + 0, 0, 0, 940, 0, 263, 0, 296, 0, 0, + 0, 249, 246, 0, 283, 0, 0, 0, 251, 0, + 264, 306, 0, 315, 280, 144, 318, 278, 277, 321, + 100, 313, 261, 269, 73, 267, 105, 98, 0, 295, + 99, 104, 87, 111, 101, 117, 123, 124, 109, 122, + 66, 115, 108, 91, 81, 82, 65, 0, 103, 76, + 80, 75, 96, 112, 113, 74, 130, 69, 121, 68, + 70, 120, 95, 110, 116, 92, 89, 67, 114, 90, + 88, 83, 78, 0, 244, 0, 107, 118, 131, 257, + 316, 125, 126, 127, 128, 94, 71, 274, 311, 255, + 256, 253, 254, 291, 292, 325, 326, 327, 307, 250, + 0, 0, 310, 294, 64, 0, 85, 129, 102, 79, + 119, 320, 309, 282, 322, 259, 273, 330, 275, 276, + 303, 247, 290, 97, 271, 0, 262, 242, 268, 243, + 260, 284, 77, 287, 258, 312, 293, 84, 328, 86, + 298, 0, 106, 93, 0, 0, 286, 314, 288, 308, + 281, 304, 252, 297, 323, 272, 301, 324, 0, 0, + 0, 62, 0, 447, 0, 0, 0, 0, 0, 0, + 72, 0, 300, 319, 270, 302, 241, 299, 0, 245, + 248, 329, 317, 265, 266, 0, 0, 0, 0, 0, + 0, 0, 285, 289, 305, 279, 0, 0, 0, 0, + 0, 0, 0, 0, 263, 0, 296, 0, 0, 0, + 249, 246, 0, 283, 0, 0, 0, 251, 0, 264, + 306, 0, 315, 280, 144, 318, 278, 277, 321, 100, + 313, 261, 269, 73, 267, 105, 98, 0, 295, 99, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 244, 0, 107, 118, 131, 257, 316, + 125, 126, 127, 128, 94, 71, 274, 311, 255, 256, + 253, 254, 291, 292, 325, 326, 327, 307, 250, 0, + 0, 310, 294, 64, 0, 85, 129, 102, 79, 119, + 320, 309, 282, 322, 259, 273, 330, 275, 276, 303, + 247, 290, 97, 271, 0, 262, 242, 268, 243, 260, + 284, 77, 287, 258, 312, 293, 84, 328, 86, 298, + 0, 106, 93, 0, 0, 286, 314, 288, 308, 281, + 304, 252, 297, 323, 272, 301, 324, 0, 0, 0, + 62, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 0, 300, 319, 270, 302, 241, 299, 0, 245, 248, + 329, 317, 265, 266, 0, 0, 0, 0, 0, 0, + 0, 285, 289, 305, 279, 0, 0, 0, 0, 0, + 0, 0, 0, 263, 0, 296, 0, 0, 0, 249, + 246, 0, 283, 0, 0, 0, 251, 0, 264, 306, + 0, 315, 280, 144, 318, 278, 277, 321, 100, 313, + 261, 269, 73, 267, 105, 98, 0, 295, 99, 104, + 87, 111, 101, 117, 123, 124, 109, 122, 66, 115, + 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, + 96, 112, 113, 74, 130, 69, 121, 68, 70, 120, + 95, 110, 116, 92, 89, 67, 114, 90, 88, 83, + 78, 0, 244, 0, 107, 118, 131, 257, 316, 125, + 126, 127, 128, 94, 71, 274, 311, 255, 256, 253, + 254, 291, 292, 325, 326, 327, 307, 250, 0, 0, + 310, 294, 64, 0, 85, 129, 102, 79, 119, 320, + 309, 282, 322, 259, 273, 330, 275, 276, 303, 247, + 290, 97, 271, 0, 262, 242, 268, 243, 260, 284, + 77, 287, 258, 312, 293, 84, 328, 86, 298, 0, + 106, 93, 0, 0, 286, 314, 288, 308, 281, 304, + 252, 297, 323, 272, 301, 324, 0, 0, 0, 208, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, + 300, 319, 270, 302, 241, 299, 0, 245, 248, 329, + 317, 265, 266, 0, 0, 0, 0, 0, 0, 0, + 285, 289, 305, 279, 0, 0, 0, 0, 0, 0, + 0, 0, 263, 0, 296, 0, 0, 0, 249, 246, + 0, 283, 0, 0, 0, 251, 0, 264, 306, 0, + 315, 280, 144, 318, 278, 277, 321, 100, 313, 261, + 269, 73, 267, 105, 98, 0, 295, 99, 104, 87, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, + 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 244, 0, 107, 118, 131, 257, 316, 125, 126, + 127, 128, 94, 71, 274, 311, 255, 256, 253, 254, + 291, 292, 325, 326, 327, 307, 250, 0, 0, 310, + 294, 64, 0, 85, 129, 102, 79, 119, 320, 309, + 282, 322, 259, 273, 330, 275, 276, 303, 247, 290, + 97, 271, 0, 262, 242, 268, 243, 260, 284, 77, + 287, 258, 312, 293, 84, 328, 86, 298, 0, 106, + 93, 0, 0, 286, 314, 288, 308, 281, 304, 252, + 297, 323, 272, 301, 324, 0, 0, 0, 142, 0, + 0, 0, 0, 0, 0, 0, 0, 72, 0, 300, + 319, 270, 302, 241, 299, 0, 245, 248, 329, 317, + 265, 266, 0, 0, 0, 0, 0, 0, 0, 285, + 289, 305, 279, 0, 0, 0, 0, 0, 0, 0, + 0, 263, 0, 296, 0, 0, 0, 249, 246, 0, + 283, 0, 0, 0, 251, 0, 264, 306, 0, 315, + 280, 144, 318, 278, 277, 321, 100, 313, 261, 269, + 73, 267, 105, 98, 0, 295, 99, 104, 87, 111, + 101, 117, 123, 124, 109, 122, 66, 115, 108, 91, + 81, 82, 65, 0, 103, 76, 80, 75, 96, 112, + 113, 74, 130, 69, 121, 68, 70, 120, 95, 110, + 116, 92, 89, 67, 114, 90, 88, 83, 78, 0, + 244, 0, 107, 118, 131, 257, 316, 125, 126, 127, + 128, 94, 71, 274, 311, 255, 256, 253, 254, 291, + 292, 325, 326, 327, 307, 250, 0, 0, 310, 294, + 64, 0, 85, 129, 102, 79, 119, 97, 0, 0, + 744, 0, 350, 0, 0, 0, 77, 0, 349, 0, + 0, 84, 388, 86, 0, 0, 106, 93, 0, 0, + 0, 0, 381, 382, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 0, 0, 208, 368, 367, 370, 371, + 372, 373, 0, 0, 72, 369, 374, 375, 376, 0, + 0, 347, 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 358, 359, 747, 0, 0, 0, 399, 0, - 360, 0, 0, 356, 357, 362, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142, 0, 0, 397, - 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, - 0, 99, 104, 87, 110, 101, 116, 121, 122, 0, - 0, 66, 114, 108, 91, 81, 82, 65, 0, 103, - 76, 80, 75, 96, 111, 112, 74, 128, 69, 120, - 68, 70, 119, 95, 109, 115, 92, 89, 67, 113, - 90, 88, 83, 78, 0, 0, 0, 107, 117, 129, - 0, 0, 123, 124, 125, 126, 94, 71, 0, 0, - 389, 398, 395, 396, 393, 394, 392, 391, 390, 400, - 383, 384, 386, 19, 385, 64, 0, 85, 127, 102, - 79, 118, 0, 0, 97, 0, 0, 0, 0, 350, + 0, 0, 0, 0, 358, 359, 747, 0, 0, 0, + 399, 0, 360, 0, 0, 356, 357, 362, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, + 0, 397, 0, 100, 0, 0, 0, 73, 0, 105, + 98, 0, 0, 99, 104, 87, 111, 101, 117, 123, + 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, + 0, 103, 76, 80, 75, 96, 112, 113, 74, 130, + 69, 121, 68, 70, 120, 95, 110, 116, 92, 89, + 67, 114, 90, 88, 83, 78, 0, 0, 0, 107, + 118, 131, 0, 0, 125, 126, 127, 128, 94, 71, + 0, 0, 389, 398, 395, 396, 393, 394, 392, 391, + 390, 400, 383, 384, 386, 0, 385, 64, 0, 85, + 129, 102, 79, 119, 97, 0, 0, 0, 0, 350, 0, 0, 0, 77, 0, 349, 0, 0, 84, 388, 86, 0, 0, 106, 93, 0, 0, 0, 0, 381, 382, 0, 0, 0, 0, 0, 0, 0, 0, 41, - 0, 0, 206, 368, 367, 370, 371, 372, 373, 0, + 0, 341, 208, 368, 367, 370, 371, 372, 373, 0, 0, 72, 369, 374, 375, 376, 0, 0, 347, 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 358, 359, 0, 0, 0, 0, 399, 0, 360, 0, 0, 356, 357, 362, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 142, 0, 0, 397, 0, + 0, 0, 0, 0, 0, 144, 0, 0, 397, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, - 99, 104, 87, 110, 101, 116, 121, 122, 0, 0, - 66, 114, 108, 91, 81, 82, 65, 0, 103, 76, - 80, 75, 96, 111, 112, 74, 128, 69, 120, 68, - 70, 119, 95, 109, 115, 92, 89, 67, 113, 90, - 88, 83, 78, 0, 0, 0, 107, 117, 129, 0, - 0, 123, 124, 125, 126, 94, 71, 0, 0, 389, + 99, 104, 87, 111, 101, 117, 123, 124, 109, 122, + 66, 115, 108, 91, 81, 82, 65, 0, 103, 76, + 80, 75, 96, 112, 113, 74, 130, 69, 121, 68, + 70, 120, 95, 110, 116, 92, 89, 67, 114, 90, + 88, 83, 78, 0, 0, 0, 107, 118, 131, 0, + 0, 125, 126, 127, 128, 94, 71, 0, 0, 389, 398, 395, 396, 393, 394, 392, 391, 390, 400, 383, - 384, 386, 0, 385, 64, 0, 85, 127, 102, 79, - 118, 97, 0, 0, 0, 0, 350, 0, 0, 0, + 384, 386, 0, 385, 64, 0, 85, 129, 102, 79, + 119, 97, 0, 0, 0, 0, 350, 0, 0, 0, 77, 0, 349, 0, 0, 84, 388, 86, 0, 0, 106, 93, 0, 0, 0, 0, 381, 382, 0, 0, - 0, 0, 0, 0, 0, 0, 41, 0, 0, 206, + 0, 0, 0, 0, 0, 0, 41, 0, 0, 208, 368, 367, 370, 371, 372, 373, 0, 0, 72, 369, 374, 375, 376, 0, 0, 347, 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 358, 359, - 0, 0, 0, 0, 399, 0, 360, 0, 0, 356, + 747, 0, 0, 0, 399, 0, 360, 0, 0, 356, 357, 362, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 142, 0, 0, 397, 0, 100, 0, 0, + 0, 0, 144, 0, 0, 397, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, 104, 87, - 110, 101, 116, 121, 122, 0, 0, 66, 114, 108, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, - 111, 112, 74, 128, 69, 120, 68, 70, 119, 95, - 109, 115, 92, 89, 67, 113, 90, 88, 83, 78, - 0, 0, 0, 107, 117, 129, 0, 0, 123, 124, - 125, 126, 94, 71, 0, 0, 389, 398, 395, 396, - 393, 394, 392, 391, 390, 400, 383, 384, 386, 97, - 385, 64, 0, 85, 127, 102, 79, 118, 77, 0, - 0, 0, 0, 84, 388, 86, 0, 0, 106, 93, - 0, 0, 0, 0, 381, 382, 0, 0, 0, 0, - 0, 0, 0, 0, 41, 0, 0, 206, 368, 367, - 370, 371, 372, 373, 0, 0, 72, 369, 374, 375, - 376, 0, 0, 0, 361, 0, 387, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 358, 359, 0, 0, - 0, 0, 399, 0, 360, 0, 0, 356, 357, 362, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 0, 0, 107, 118, 131, 0, 0, 125, 126, + 127, 128, 94, 71, 0, 0, 389, 398, 395, 396, + 393, 394, 392, 391, 390, 400, 383, 384, 386, 19, + 385, 64, 0, 85, 129, 102, 79, 119, 0, 0, + 97, 0, 0, 0, 0, 350, 0, 0, 0, 77, + 0, 349, 0, 0, 84, 388, 86, 0, 0, 106, + 93, 0, 0, 0, 0, 381, 382, 0, 0, 0, + 0, 0, 0, 0, 0, 41, 0, 0, 208, 368, + 367, 370, 371, 372, 373, 0, 0, 72, 369, 374, + 375, 376, 0, 0, 347, 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 397, 0, 100, 0, 0, 0, 73, - 0, 105, 98, 0, 1083, 99, 104, 87, 110, 101, - 116, 121, 122, 0, 0, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 0, - 0, 107, 117, 129, 0, 0, 123, 124, 125, 126, - 94, 71, 0, 0, 389, 398, 395, 396, 393, 394, - 392, 391, 390, 400, 383, 384, 386, 97, 385, 64, - 0, 85, 127, 102, 79, 118, 77, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 358, 359, 0, + 0, 0, 0, 399, 0, 360, 0, 0, 356, 357, + 362, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 144, 0, 0, 397, 0, 100, 0, 0, 0, + 73, 0, 105, 98, 0, 0, 99, 104, 87, 111, + 101, 117, 123, 124, 109, 122, 66, 115, 108, 91, + 81, 82, 65, 0, 103, 76, 80, 75, 96, 112, + 113, 74, 130, 69, 121, 68, 70, 120, 95, 110, + 116, 92, 89, 67, 114, 90, 88, 83, 78, 0, + 0, 0, 107, 118, 131, 0, 0, 125, 126, 127, + 128, 94, 71, 0, 0, 389, 398, 395, 396, 393, + 394, 392, 391, 390, 400, 383, 384, 386, 0, 385, + 64, 0, 85, 129, 102, 79, 119, 97, 0, 0, + 0, 0, 350, 0, 0, 0, 77, 0, 349, 0, 0, 84, 388, 86, 0, 0, 106, 93, 0, 0, 0, 0, 381, 382, 0, 0, 0, 0, 0, 0, - 0, 0, 41, 0, 0, 206, 368, 367, 370, 371, + 0, 0, 41, 0, 0, 208, 368, 367, 370, 371, 372, 373, 0, 0, 72, 369, 374, 375, 376, 0, - 0, 0, 361, 0, 387, 0, 0, 0, 0, 0, + 0, 347, 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 358, 359, 0, 0, 0, 0, 399, 0, 360, 0, 0, 356, 357, 362, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 397, 0, 100, 0, 0, 0, 73, 0, 105, - 98, 0, 0, 99, 104, 87, 110, 101, 116, 121, - 122, 0, 0, 66, 114, 108, 91, 81, 82, 65, - 0, 103, 76, 80, 75, 96, 111, 112, 74, 128, - 69, 120, 68, 70, 119, 95, 109, 115, 92, 89, - 67, 113, 90, 88, 83, 78, 0, 0, 0, 107, - 117, 129, 0, 0, 123, 124, 125, 126, 94, 71, + 98, 0, 0, 99, 104, 87, 111, 101, 117, 123, + 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, + 0, 103, 76, 80, 75, 96, 112, 113, 74, 130, + 69, 121, 68, 70, 120, 95, 110, 116, 92, 89, + 67, 114, 90, 88, 83, 78, 0, 0, 0, 107, + 118, 131, 0, 0, 125, 126, 127, 128, 94, 71, 0, 0, 389, 398, 395, 396, 393, 394, 392, 391, 390, 400, 383, 384, 386, 97, 385, 64, 0, 85, - 127, 102, 79, 118, 77, 0, 0, 0, 0, 84, - 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, + 129, 102, 79, 119, 77, 0, 0, 0, 0, 84, + 388, 86, 0, 0, 106, 93, 0, 0, 0, 0, + 381, 382, 0, 0, 0, 0, 0, 0, 0, 0, + 41, 0, 0, 208, 368, 367, 370, 371, 372, 373, + 0, 0, 72, 369, 374, 375, 376, 0, 0, 0, + 361, 0, 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 531, 530, - 540, 541, 533, 534, 535, 536, 537, 538, 539, 532, - 0, 0, 542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, + 0, 0, 358, 359, 0, 0, 0, 0, 399, 0, + 360, 0, 0, 356, 357, 362, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 144, 0, 0, 397, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, - 0, 99, 104, 87, 110, 101, 116, 121, 122, 0, - 0, 66, 114, 108, 91, 81, 82, 65, 0, 103, - 76, 80, 75, 96, 111, 112, 74, 128, 69, 120, - 68, 70, 119, 95, 109, 115, 92, 89, 67, 113, - 90, 88, 83, 78, 0, 0, 0, 107, 117, 129, - 0, 0, 123, 124, 125, 126, 94, 71, 0, 0, + 1083, 99, 104, 87, 111, 101, 117, 123, 124, 109, + 122, 66, 115, 108, 91, 81, 82, 65, 0, 103, + 76, 80, 75, 96, 112, 113, 74, 130, 69, 121, + 68, 70, 120, 95, 110, 116, 92, 89, 67, 114, + 90, 88, 83, 78, 0, 0, 0, 107, 118, 131, + 0, 0, 125, 126, 127, 128, 94, 71, 0, 0, + 389, 398, 395, 396, 393, 394, 392, 391, 390, 400, + 383, 384, 386, 97, 385, 64, 0, 85, 129, 102, + 79, 119, 77, 0, 0, 0, 0, 84, 388, 86, + 0, 0, 106, 93, 0, 0, 0, 0, 381, 382, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, + 0, 208, 368, 367, 370, 371, 372, 373, 0, 0, + 72, 369, 374, 375, 376, 0, 0, 0, 361, 0, + 387, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64, 0, 85, 127, 102, - 79, 118, 97, 0, 0, 0, 857, 0, 0, 0, - 0, 77, 0, 0, 0, 0, 84, 0, 86, 0, - 0, 106, 93, 0, 0, 0, 0, 0, 0, 0, + 358, 359, 0, 0, 0, 0, 399, 0, 360, 0, + 0, 356, 357, 362, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 0, 0, 397, 0, 100, + 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 0, 0, 107, 118, 131, 0, 0, + 125, 126, 127, 128, 94, 71, 0, 0, 389, 398, + 395, 396, 393, 394, 392, 391, 390, 400, 383, 384, + 386, 97, 385, 64, 0, 85, 129, 102, 79, 119, + 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, + 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 531, 530, 540, 541, 533, 534, + 535, 536, 537, 538, 539, 532, 0, 0, 542, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, + 0, 73, 0, 105, 98, 0, 0, 99, 104, 87, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, + 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 0, 0, 107, 118, 131, 97, 0, 125, 126, + 127, 128, 94, 71, 0, 77, 0, 0, 0, 0, + 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, + 0, 64, 0, 85, 129, 102, 79, 119, 0, 0, + 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, + 0, 0, 0, 72, 0, 0, 0, 0, 58, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 59, 0, 57, 0, 0, + 0, 60, 100, 0, 0, 0, 73, 0, 105, 98, + 0, 0, 99, 104, 87, 111, 101, 117, 123, 124, + 109, 122, 66, 115, 108, 91, 81, 82, 65, 0, + 103, 76, 80, 75, 96, 112, 113, 74, 130, 69, + 121, 68, 70, 120, 95, 110, 116, 92, 89, 67, + 114, 90, 88, 83, 78, 0, 0, 0, 107, 118, + 131, 0, 0, 125, 126, 127, 128, 94, 71, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 64, 0, 85, 129, + 102, 79, 119, 97, 0, 0, 0, 435, 0, 0, + 0, 0, 77, 0, 0, 0, 0, 84, 0, 86, + 0, 0, 106, 93, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 142, 0, 437, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 0, 0, 0, 0, 100, + 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 0, 0, 107, 118, 131, 0, 0, + 125, 126, 127, 128, 94, 71, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 97, 0, 64, 0, 85, 129, 102, 79, 119, + 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, + 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 41, 0, 0, 62, + 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 62, 0, 859, 0, 0, 0, 0, 0, 0, 72, - 0, 0, 0, 0, 519, 518, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 520, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 0, 0, 0, 0, 100, 0, - 0, 0, 73, 0, 105, 98, 0, 0, 99, 104, - 87, 110, 101, 116, 121, 122, 0, 0, 66, 114, - 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, - 96, 111, 112, 74, 128, 69, 120, 68, 70, 119, - 95, 109, 115, 92, 89, 67, 113, 90, 88, 83, - 78, 0, 0, 0, 107, 117, 129, 0, 0, 123, - 124, 125, 126, 94, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 64, 0, 85, 127, 102, 79, 118, 97, - 0, 0, 0, 435, 0, 0, 0, 0, 77, 0, + 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, + 0, 73, 0, 105, 98, 0, 0, 99, 104, 87, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, + 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 0, 0, 107, 118, 131, 0, 0, 125, 126, + 127, 128, 94, 71, 0, 0, 0, 0, 19, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, + 0, 64, 0, 85, 129, 102, 79, 119, 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 140, 0, 437, + 0, 0, 0, 0, 41, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 0, 0, 100, 0, 0, 0, 73, - 0, 105, 98, 0, 0, 99, 104, 87, 110, 101, - 116, 121, 122, 0, 0, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 0, - 0, 107, 117, 129, 0, 0, 123, 124, 125, 126, - 94, 71, 0, 0, 0, 0, 19, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 97, 0, 64, - 0, 85, 127, 102, 79, 118, 77, 0, 0, 0, - 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, + 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, + 0, 105, 98, 0, 0, 99, 104, 87, 111, 101, + 117, 123, 124, 109, 122, 66, 115, 108, 91, 81, + 82, 65, 0, 103, 76, 80, 75, 96, 112, 113, + 74, 130, 69, 121, 68, 70, 120, 95, 110, 116, + 92, 89, 67, 114, 90, 88, 83, 78, 0, 0, + 0, 107, 118, 131, 97, 0, 125, 126, 127, 128, + 94, 71, 0, 77, 0, 0, 0, 0, 84, 0, + 86, 0, 0, 106, 93, 0, 0, 0, 0, 64, + 0, 85, 129, 102, 79, 119, 0, 0, 0, 0, + 0, 0, 62, 0, 0, 599, 0, 0, 600, 0, + 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 41, 0, 0, 62, 0, 0, 0, 0, - 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, + 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, + 99, 104, 87, 111, 101, 117, 123, 124, 109, 122, + 66, 115, 108, 91, 81, 82, 65, 0, 103, 76, + 80, 75, 96, 112, 113, 74, 130, 69, 121, 68, + 70, 120, 95, 110, 116, 92, 89, 67, 114, 90, + 88, 83, 78, 0, 0, 0, 107, 118, 131, 0, + 0, 125, 126, 127, 128, 94, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, - 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, - 98, 0, 0, 99, 104, 87, 110, 101, 116, 121, - 122, 0, 0, 66, 114, 108, 91, 81, 82, 65, - 0, 103, 76, 80, 75, 96, 111, 112, 74, 128, - 69, 120, 68, 70, 119, 95, 109, 115, 92, 89, - 67, 113, 90, 88, 83, 78, 0, 0, 0, 107, - 117, 129, 0, 0, 123, 124, 125, 126, 94, 71, - 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 97, 0, 64, 0, 85, - 127, 102, 79, 118, 77, 0, 0, 0, 0, 84, - 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, + 0, 0, 0, 0, 64, 0, 85, 129, 102, 79, + 119, 97, 0, 0, 0, 435, 0, 0, 0, 0, + 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, + 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, + 0, 437, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 41, 0, 0, 140, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, - 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, - 0, 99, 104, 87, 110, 101, 116, 121, 122, 0, - 0, 66, 114, 108, 91, 81, 82, 65, 0, 103, - 76, 80, 75, 96, 111, 112, 74, 128, 69, 120, - 68, 70, 119, 95, 109, 115, 92, 89, 67, 113, - 90, 88, 83, 78, 0, 0, 0, 107, 117, 129, - 97, 0, 123, 124, 125, 126, 94, 71, 0, 77, - 0, 0, 0, 0, 84, 0, 86, 0, 0, 106, - 93, 0, 0, 0, 0, 64, 0, 85, 127, 102, - 79, 118, 0, 0, 0, 0, 0, 0, 62, 0, - 0, 599, 0, 0, 600, 0, 0, 72, 0, 0, + 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, + 0, 73, 0, 105, 98, 0, 0, 433, 104, 87, + 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, + 91, 81, 82, 65, 0, 103, 76, 80, 75, 96, + 112, 113, 74, 130, 69, 121, 68, 70, 120, 95, + 110, 116, 92, 89, 67, 114, 90, 88, 83, 78, + 0, 0, 0, 107, 118, 131, 97, 0, 125, 126, + 127, 128, 94, 71, 0, 77, 0, 0, 0, 0, + 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, + 0, 64, 0, 85, 129, 102, 79, 119, 0, 0, + 0, 0, 0, 0, 208, 0, 0, 0, 0, 0, + 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, + 0, 0, 100, 0, 0, 0, 73, 0, 105, 98, + 0, 0, 99, 104, 87, 111, 101, 117, 123, 124, + 109, 122, 66, 115, 108, 91, 81, 82, 65, 0, + 103, 76, 80, 75, 96, 112, 113, 74, 130, 69, + 121, 68, 203, 120, 95, 110, 116, 92, 89, 67, + 114, 90, 88, 83, 78, 0, 0, 0, 107, 118, + 131, 0, 97, 125, 126, 127, 128, 204, 202, 201, + 200, 77, 0, 0, 0, 0, 84, 0, 86, 0, + 0, 106, 93, 0, 0, 0, 64, 0, 85, 129, + 102, 79, 119, 0, 0, 0, 0, 41, 0, 0, + 142, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 142, 0, 0, 0, 0, 100, 0, 0, 0, - 73, 0, 105, 98, 0, 0, 99, 104, 87, 110, - 101, 116, 121, 122, 0, 0, 66, 114, 108, 91, - 81, 82, 65, 0, 103, 76, 80, 75, 96, 111, - 112, 74, 128, 69, 120, 68, 70, 119, 95, 109, - 115, 92, 89, 67, 113, 90, 88, 83, 78, 0, - 0, 0, 107, 117, 129, 0, 0, 123, 124, 125, - 126, 94, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 64, 0, 85, 127, 102, 79, 118, 97, 0, 0, - 0, 435, 0, 0, 0, 0, 77, 0, 0, 0, - 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 140, 0, 437, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 144, 0, 0, 0, 0, 100, 0, + 0, 0, 73, 0, 105, 98, 0, 0, 99, 104, + 87, 111, 101, 117, 123, 124, 109, 122, 66, 115, + 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, + 96, 112, 113, 74, 130, 69, 121, 68, 70, 120, + 95, 110, 116, 92, 89, 67, 114, 90, 88, 83, + 78, 0, 0, 0, 107, 118, 131, 97, 0, 125, + 126, 127, 128, 94, 71, 0, 77, 0, 0, 0, + 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, + 0, 0, 64, 0, 85, 129, 102, 79, 119, 0, + 0, 0, 0, 0, 0, 62, 0, 859, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 142, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, - 98, 0, 0, 433, 104, 87, 110, 101, 116, 121, - 122, 0, 0, 66, 114, 108, 91, 81, 82, 65, - 0, 103, 76, 80, 75, 96, 111, 112, 74, 128, - 69, 120, 68, 70, 119, 95, 109, 115, 92, 89, - 67, 113, 90, 88, 83, 78, 0, 0, 0, 107, - 117, 129, 97, 0, 123, 124, 125, 126, 94, 71, + 98, 0, 0, 99, 104, 87, 111, 101, 117, 123, + 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, + 0, 103, 76, 80, 75, 96, 112, 113, 74, 130, + 69, 121, 68, 70, 120, 95, 110, 116, 92, 89, + 67, 114, 90, 88, 83, 78, 0, 0, 0, 107, + 118, 131, 97, 0, 125, 126, 127, 128, 94, 71, 0, 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, 64, 0, 85, - 127, 102, 79, 118, 0, 0, 0, 0, 0, 0, - 206, 0, 0, 0, 0, 0, 0, 0, 0, 72, + 129, 102, 79, 119, 0, 0, 0, 0, 0, 0, + 142, 0, 437, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 142, 0, 0, 0, 0, 100, 0, + 0, 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, 104, - 87, 110, 101, 116, 121, 122, 0, 0, 66, 114, + 87, 111, 101, 117, 123, 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, 75, - 96, 111, 112, 74, 128, 69, 120, 68, 201, 119, - 95, 109, 115, 92, 89, 67, 113, 90, 88, 83, - 78, 0, 0, 0, 107, 117, 129, 0, 97, 123, - 124, 125, 126, 202, 200, 199, 198, 77, 0, 0, - 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, - 0, 0, 64, 0, 85, 127, 102, 79, 118, 0, - 0, 0, 0, 41, 0, 0, 140, 0, 0, 0, - 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, + 96, 112, 113, 74, 130, 69, 121, 68, 70, 120, + 95, 110, 116, 92, 89, 67, 114, 90, 88, 83, + 78, 0, 0, 0, 107, 118, 131, 97, 0, 125, + 126, 127, 128, 94, 71, 412, 77, 0, 0, 0, + 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, + 0, 0, 64, 0, 85, 129, 102, 79, 119, 0, + 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, - 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, - 105, 98, 0, 0, 99, 104, 87, 110, 101, 116, - 121, 122, 0, 0, 66, 114, 108, 91, 81, 82, - 65, 0, 103, 76, 80, 75, 96, 111, 112, 74, - 128, 69, 120, 68, 70, 119, 95, 109, 115, 92, - 89, 67, 113, 90, 88, 83, 78, 0, 0, 0, - 107, 117, 129, 97, 0, 123, 124, 125, 126, 94, - 71, 0, 77, 0, 0, 0, 0, 84, 0, 86, - 0, 0, 106, 93, 0, 0, 0, 0, 64, 0, - 85, 127, 102, 79, 118, 0, 0, 0, 0, 0, - 0, 62, 0, 859, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 144, 0, + 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, + 98, 0, 0, 99, 104, 87, 111, 101, 117, 123, + 124, 109, 122, 66, 115, 108, 91, 81, 82, 65, + 0, 103, 76, 80, 75, 96, 112, 113, 74, 130, + 69, 121, 68, 70, 120, 95, 110, 116, 92, 89, + 67, 114, 90, 88, 83, 78, 193, 0, 0, 107, + 118, 131, 0, 97, 125, 126, 127, 128, 94, 71, + 0, 0, 77, 0, 0, 0, 0, 84, 0, 86, + 0, 0, 106, 93, 0, 0, 0, 64, 0, 85, + 129, 102, 79, 119, 0, 0, 0, 0, 0, 0, + 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 142, 0, 0, 0, 0, 100, + 0, 0, 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, - 104, 87, 110, 101, 116, 121, 122, 0, 0, 66, - 114, 108, 91, 81, 82, 65, 0, 103, 76, 80, - 75, 96, 111, 112, 74, 128, 69, 120, 68, 70, - 119, 95, 109, 115, 92, 89, 67, 113, 90, 88, - 83, 78, 0, 0, 0, 107, 117, 129, 97, 0, - 123, 124, 125, 126, 94, 71, 0, 77, 0, 0, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 0, 0, 107, 118, 131, 97, 0, + 125, 126, 127, 128, 94, 71, 0, 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, - 0, 0, 0, 64, 0, 85, 127, 102, 79, 118, - 0, 0, 0, 0, 0, 0, 140, 0, 437, 0, + 0, 0, 0, 64, 0, 85, 129, 102, 79, 119, + 0, 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 142, + 0, 0, 0, 0, 0, 0, 0, 139, 0, 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, - 105, 98, 0, 0, 99, 104, 87, 110, 101, 116, - 121, 122, 0, 0, 66, 114, 108, 91, 81, 82, - 65, 0, 103, 76, 80, 75, 96, 111, 112, 74, - 128, 69, 120, 68, 70, 119, 95, 109, 115, 92, - 89, 67, 113, 90, 88, 83, 78, 0, 0, 0, - 107, 117, 129, 97, 0, 123, 124, 125, 126, 94, - 71, 412, 77, 0, 0, 0, 0, 84, 0, 86, + 105, 98, 0, 0, 99, 104, 87, 111, 101, 117, + 123, 124, 109, 122, 66, 115, 108, 91, 81, 82, + 65, 0, 103, 76, 80, 75, 96, 112, 113, 74, + 130, 69, 121, 68, 70, 120, 95, 110, 116, 92, + 89, 67, 114, 90, 88, 83, 78, 0, 0, 0, + 107, 118, 131, 97, 0, 125, 126, 127, 128, 94, + 71, 0, 77, 0, 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, 0, 0, 0, 64, 0, - 85, 127, 102, 79, 118, 0, 0, 0, 0, 0, - 0, 140, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 129, 102, 79, 119, 0, 0, 0, 0, 0, + 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 142, 0, 0, 0, 0, 100, + 0, 0, 0, 0, 144, 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, - 104, 87, 110, 101, 116, 121, 122, 0, 0, 66, - 114, 108, 91, 81, 82, 65, 0, 103, 76, 80, - 75, 96, 111, 112, 74, 128, 69, 120, 68, 70, - 119, 95, 109, 115, 92, 89, 67, 113, 90, 88, - 83, 78, 191, 0, 0, 107, 117, 129, 0, 97, - 123, 124, 125, 126, 94, 71, 0, 0, 77, 0, - 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, - 0, 0, 0, 64, 0, 85, 127, 102, 79, 118, - 0, 0, 0, 0, 0, 0, 0, 140, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 0, 0, 100, 0, 0, 0, 73, - 0, 105, 98, 0, 0, 99, 104, 87, 110, 101, - 116, 121, 122, 0, 0, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 0, - 0, 107, 117, 129, 97, 0, 123, 124, 125, 126, - 94, 71, 0, 77, 0, 0, 0, 0, 84, 0, - 86, 0, 0, 106, 93, 0, 0, 0, 0, 64, - 0, 85, 127, 102, 79, 118, 0, 0, 0, 0, - 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, - 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 137, 0, 142, 0, 0, 0, 0, - 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, - 99, 104, 87, 110, 101, 116, 121, 122, 0, 0, - 66, 114, 108, 91, 81, 82, 65, 0, 103, 76, - 80, 75, 96, 111, 112, 74, 128, 69, 120, 68, - 70, 119, 95, 109, 115, 92, 89, 67, 113, 90, - 88, 83, 78, 0, 0, 0, 107, 117, 129, 97, - 0, 123, 124, 125, 126, 94, 71, 0, 77, 0, - 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, - 0, 0, 0, 0, 64, 0, 85, 127, 102, 79, - 118, 0, 0, 0, 0, 0, 0, 62, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 0, 0, 100, 0, 0, 0, 73, - 0, 105, 98, 0, 0, 99, 104, 87, 110, 101, - 116, 121, 122, 0, 0, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 0, - 0, 107, 117, 129, 97, 0, 123, 124, 125, 126, - 94, 71, 0, 77, 0, 0, 0, 0, 84, 0, - 86, 0, 0, 106, 93, 0, 0, 0, 0, 64, - 0, 85, 127, 102, 79, 118, 0, 0, 0, 0, - 0, 0, 206, 0, 0, 0, 0, 0, 0, 0, - 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 0, 0, 107, 118, 131, 97, 0, + 125, 126, 127, 128, 94, 71, 0, 77, 0, 0, + 0, 0, 84, 0, 86, 0, 0, 106, 93, 0, + 0, 0, 0, 64, 0, 85, 129, 102, 79, 119, + 0, 0, 0, 0, 0, 0, 208, 0, 0, 0, + 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 142, 0, 0, 0, 0, - 100, 0, 0, 0, 73, 0, 105, 98, 0, 0, - 99, 104, 87, 110, 101, 116, 121, 122, 0, 0, - 66, 114, 108, 91, 81, 82, 65, 0, 103, 76, - 80, 75, 96, 111, 112, 74, 128, 69, 120, 68, - 70, 119, 95, 109, 115, 92, 89, 67, 113, 90, - 88, 83, 78, 0, 0, 0, 107, 117, 129, 97, - 0, 123, 124, 125, 126, 94, 71, 0, 77, 0, - 0, 0, 0, 84, 0, 86, 0, 0, 106, 93, - 0, 0, 0, 0, 64, 0, 85, 127, 102, 79, - 118, 0, 0, 0, 0, 0, 0, 140, 0, 0, - 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, + 0, 0, 0, 0, 100, 0, 0, 0, 73, 0, + 105, 98, 0, 0, 99, 104, 87, 111, 101, 117, + 123, 124, 109, 122, 66, 115, 108, 91, 81, 82, + 65, 0, 103, 76, 80, 75, 96, 112, 113, 74, + 130, 69, 121, 68, 70, 120, 95, 110, 116, 92, + 89, 67, 114, 90, 88, 83, 78, 0, 0, 0, + 107, 118, 131, 97, 0, 125, 126, 127, 128, 94, + 71, 0, 77, 0, 0, 0, 0, 84, 0, 86, + 0, 0, 106, 93, 0, 0, 0, 0, 64, 0, + 85, 129, 102, 79, 119, 0, 0, 0, 0, 0, + 0, 142, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 144, 0, 0, 0, 0, 100, + 0, 0, 0, 73, 0, 105, 98, 0, 0, 99, + 104, 87, 111, 101, 117, 123, 124, 109, 122, 66, + 115, 108, 91, 81, 82, 65, 0, 103, 76, 80, + 75, 96, 112, 113, 74, 130, 69, 121, 68, 70, + 120, 95, 110, 116, 92, 89, 67, 114, 90, 88, + 83, 78, 0, 0, 0, 107, 118, 131, 0, 0, + 125, 126, 127, 128, 94, 71, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 142, 0, 0, 0, 0, 100, 0, 0, 0, 73, - 0, 105, 98, 0, 0, 99, 104, 87, 110, 101, - 116, 121, 122, 0, 0, 66, 114, 108, 91, 81, - 82, 65, 0, 103, 76, 80, 75, 96, 111, 112, - 74, 128, 69, 120, 68, 70, 119, 95, 109, 115, - 92, 89, 67, 113, 90, 88, 83, 78, 0, 0, - 0, 107, 117, 129, 0, 0, 123, 124, 125, 126, - 94, 71, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, - 0, 85, 127, 102, 79, 118, + 0, 0, 0, 64, 0, 85, 129, 102, 79, 119, } var yyPact = [...]int{ - 1693, -1000, -158, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 742, 762, -1000, - -1000, -1000, -1000, -1000, 576, 1496, 6, 48, 52, 7477, - 42, 60, 7972, -1000, -1000, -1000, -1000, -1000, 558, -1000, - -1000, -1000, -1000, -1000, 733, 738, 573, 714, 651, -1000, - 3, 6651, 7312, 6485, -1000, 441, 27, 7972, -131, 0, + 161, -1000, -161, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 752, 771, -1000, + -1000, -1000, -1000, -1000, 573, 5429, -12, 56, 42, 7521, + 38, 1212, 8016, -1000, -1000, -1000, -1000, -1000, 524, -1000, + -1000, -1000, -1000, -1000, 745, 750, 589, 737, 660, -1000, + 5, 6695, 7356, 6529, -1000, 372, 54, 8016, -133, -16, -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, @@ -1391,17 +1395,17 @@ 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, - 30, 7972, -1000, 7972, -1, 428, -1, 7972, -1000, 99, - -1000, -1000, -1000, 7972, 416, 684, 19, 2592, 2592, 2592, - 2592, -52, 2592, 2592, 590, -1000, -1000, -1000, -1000, 2592, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 395, 682, - 4624, 4624, 742, -1000, 558, -1000, -1000, -1000, 677, -1000, - -1000, 221, 7146, 527, 571, -1000, -1000, -1000, 711, 5958, - 6320, 7972, 524, -1000, 500, 7807, 3010, -1000, -1000, -1000, - -1000, 674, -1000, 173, -1000, 96, -1000, -1000, 476, -1000, - 1758, 412, 2592, 15, 7972, 198, 7972, 2592, 9, 7972, - 701, 589, 7972, -1000, 3637, -1000, 2592, 2592, 2592, 2592, - 2592, 2592, 2592, 2592, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 29, 8016, -1000, 8016, -18, 370, -18, 8016, + -1000, 94, -1000, -1000, -1000, 8016, 368, 707, 28, 2668, + 2668, 2668, 2668, -57, 2668, 2668, 586, -1000, -1000, -1000, + -1000, 2668, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 350, 704, 4700, 4700, 752, -1000, 524, -1000, -1000, -1000, + 697, -1000, -1000, 217, 7190, 553, 784, -1000, -1000, -1000, + 734, 6002, 6364, 8016, 550, -1000, 401, 7851, 3086, -1000, + -1000, -1000, -1000, 701, -1000, 139, -1000, 89, -1000, -1000, + 519, -1000, 1334, 358, 2668, 24, 8016, 166, 8016, 2668, + 21, 8016, 730, 584, 8016, -1000, 3713, -1000, 2668, 2668, + 2668, 2668, 2668, 2668, 2668, 2668, -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, @@ -1411,102 +1415,102 @@ 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, 2592, 2592, -1000, -1000, 7972, -1000, - -1000, -1000, -1000, 757, 130, 452, -1000, 4624, 1863, 548, - 548, -1000, -1000, 64, -1000, -1000, 5000, 5000, 5000, 5000, - 5000, 5000, 5000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 548, 93, -1000, - 4427, 548, 548, 548, 548, 548, 548, 4624, 548, 548, - 548, 548, 548, 548, 548, 548, 548, 548, 548, 548, - 548, 531, -1000, 248, 733, 395, 651, 6123, 582, -1000, - -1000, -15, 7972, -1000, 7807, 6651, 6651, 6651, 6651, 6651, - -1000, 616, 613, -1000, 636, 609, 642, 7972, -1000, 474, - 395, 5958, 83, 548, -1000, 6981, -1000, -1000, -15, 6651, - 7972, -1000, -1000, 7807, 500, -1000, -1000, -1000, -1000, 4624, - 3428, 2174, 136, 259, -104, -1000, -1000, 551, -1000, 551, - 551, 551, 551, -81, -81, -81, -81, -1000, -1000, -1000, - -1000, -1000, 574, -1000, 551, 551, 551, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 572, 572, 572, 554, 554, - 550, -1000, 7972, -1000, 700, 72, -1000, 7972, -1000, -1000, - 7972, 2592, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 643, 4624, 4624, - 359, 4624, 4624, 135, 5000, 291, 152, 5000, 5000, 5000, - 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, - 5000, 5000, 374, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 386, -1000, 558, 680, 680, 107, 107, 107, 107, - 107, 107, 5188, 3834, 3428, 453, 195, 4427, 4228, 4228, - 4624, 4624, 4228, 715, 187, 195, 7642, -1000, 395, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 4228, 4228, 4228, 4228, - 4624, -1000, -1000, -1000, 682, -1000, 715, 737, -1000, 667, - 666, 4228, -1000, 526, 548, -1000, 549, 571, 570, 588, - 824, -1000, -1000, -1000, -1000, 603, -1000, 602, -1000, -1000, - -1000, -1000, -1000, 395, -1000, 23, 21, 17, 7642, -1000, - 749, 532, -1000, -1000, -1000, 195, -1000, 91, -1000, 530, - 1965, -1000, -1000, -1000, -1000, -1000, -1000, 557, 692, 171, - 382, -1000, -1000, 686, -1000, 210, -109, -1000, -1000, 306, - -81, -81, -1000, -1000, 76, 673, 76, 76, 76, 356, - -1000, -1000, -1000, -1000, 297, -1000, -1000, -1000, 287, -1000, - 587, 7642, 2592, -1000, -1000, 98, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -16, -1000, - 2592, -1000, 658, 135, 241, -1000, -1000, 271, -1000, -1000, - 195, 195, 1214, -1000, -1000, -1000, -1000, 291, 5000, 5000, - 5000, 200, 1214, 1125, 989, 311, 107, 209, 209, 153, - 153, 153, 153, 153, 495, 495, -1000, -1000, -1000, 395, - -1000, -1000, -1000, 395, 4228, 520, -1000, -1000, 5385, 81, - 548, 4624, -1000, 422, 422, 217, 254, 422, 4228, 256, - -1000, 4624, 395, -1000, 422, 395, 422, 422, -1000, -1000, - 7972, -1000, -1000, -1000, -1000, 529, 586, 7807, 548, -1000, - 5770, 7642, 742, 4624, -1000, -1000, 4624, 555, -1000, 4624, - -1000, -1000, -1000, -1000, 548, 548, 548, 402, -1000, 742, - -1000, 3219, 2174, -1000, 2174, 7642, -1000, 380, -1000, -1000, - 584, 22, -1000, -1000, -1000, 477, 76, 76, -1000, 378, - 155, -1000, -1000, -1000, 446, -1000, 518, 432, 7972, -1000, - -1000, -1000, 7972, -1000, -1000, -1000, -1000, -1000, 7642, -1000, - -1000, -1000, -1000, -1000, -1000, 200, 1214, 1073, -1000, 5000, - 5000, -1000, -1000, 422, 4228, -1000, -1000, 6816, -1000, -1000, - 2801, 4228, 195, -1000, -1000, -13, 374, -13, -139, 506, - 178, -1000, 4624, 246, -1000, -1000, -1000, -1000, -1000, -1000, - 749, 6651, -1000, 694, 491, 510, -1000, -1000, 4031, 395, - 406, 75, 402, 733, 195, 195, 7642, 195, 7642, 7642, - 7642, 5582, 7642, 733, -1000, 1965, -1000, 400, -1000, 551, - -1000, -100, 756, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 331, 283, -1000, 244, 2592, - -1000, -1000, 696, -1000, 5000, 1214, 1214, -1000, -1000, -1000, - -1000, 70, 395, 395, 551, 551, -1000, 551, 554, -1000, - 551, -63, 551, -65, 395, 395, 548, -136, -1000, 195, - 4624, 747, 514, 691, -1000, 548, -1000, -1000, 534, 7642, - 7642, -1000, -1000, 398, -1000, 394, 394, 394, 83, -1000, - -1000, -1000, 7642, -1000, 115, -1000, -121, -1000, 447, 403, - -1000, 548, 1214, 2383, -1000, -1000, -1000, 29, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, -1000, 5000, 395, 323, 195, - 744, 735, 753, -1000, 548, -1000, 558, 31, -1000, 7642, - -1000, -1000, -1000, -1000, -1000, -1000, 202, 690, -1000, 689, - -1000, -1000, -1000, -34, -1000, -1000, -1000, 12, -1000, -1000, - -1000, 4624, 4624, 7807, 510, 395, 7642, -1000, -1000, 257, - -1000, -1000, 369, -1000, 7642, 395, 28, -148, 195, 509, - 500, -1000, -1000, -1000, -1000, -34, 664, -1000, 654, -142, - -153, -1000, -37, -1000, 649, -1000, -39, -144, 548, -150, - 4812, -155, 275, 395, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 2668, 2668, -1000, -1000, 8016, -1000, + -1000, -1000, -1000, 781, 127, 508, -1000, 4700, 1749, 541, + 541, -1000, -1000, 66, -1000, -1000, 5076, 5076, 5076, 5076, + 5076, 5076, 5076, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 541, 88, -1000, + 4503, 541, 541, 541, 541, 541, 541, 4700, 541, 541, + 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, + 541, 475, -1000, 405, 745, 350, 660, 6167, 597, -1000, + -1000, -31, 8016, -1000, 7851, 6695, 6695, 6695, 6695, 6695, + -1000, 634, 631, -1000, 650, 600, 651, 8016, -1000, 516, + 350, 6002, 125, 541, -1000, 7025, -1000, -1000, -31, 6695, + 8016, -1000, -1000, 7851, 401, -1000, -1000, -1000, -1000, 4700, + 3504, 2250, 187, 227, -109, -1000, -1000, 544, -1000, 544, + 544, 544, 544, -89, -89, -89, -89, -1000, -1000, -1000, + -1000, -1000, 572, -1000, 544, 544, 544, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 563, 563, 563, 555, 555, + 540, -1000, 8016, -1000, 724, 93, -1000, 8016, -1000, -1000, + 8016, 2668, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, 680, 4700, 4700, + 343, 4700, 4700, 131, 5076, 237, 170, 5076, 5076, 5076, + 5076, 5076, 5076, 5076, 5076, 5076, 5076, 5076, 5076, 5076, + 5076, 5076, 275, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 333, -1000, 524, 842, 842, 108, 108, 108, 108, + 108, 108, 5264, 3910, 3504, 510, 338, 4503, 4304, 4304, + 4700, 4700, 4304, 738, 149, 338, 7686, -1000, 350, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 4304, 4304, 4304, 4304, + 4700, -1000, -1000, -1000, 704, -1000, 738, 753, -1000, 689, + 687, 4304, -1000, 556, 541, -1000, 570, 784, 569, 581, + 638, -1000, -1000, -1000, -1000, 630, -1000, 608, -1000, -1000, + -1000, -1000, -1000, 350, -1000, 47, 46, 44, 7686, -1000, + 762, 564, -1000, -1000, -1000, 338, -1000, 87, -1000, 470, + 2041, -1000, -1000, -1000, -1000, -1000, -1000, 559, 715, 183, + 324, -1000, -1000, 705, -1000, 182, -111, -1000, -1000, 269, + -89, -89, -1000, -1000, 97, 700, 97, 97, 97, 281, + -1000, -1000, -1000, -1000, 268, -1000, -1000, -1000, 253, -1000, + 571, 7686, 2668, -1000, -1000, 122, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -39, -1000, + 2668, -1000, 668, 131, 198, -1000, -1000, 371, -1000, -1000, + 338, 338, 1124, -1000, -1000, -1000, -1000, 237, 5076, 5076, + 5076, 19, 1124, 1001, 276, 1328, 108, 257, 257, 107, + 107, 107, 107, 107, 248, 248, -1000, -1000, -1000, 350, + -1000, -1000, -1000, 350, 4304, 460, -1000, -1000, 1614, 86, + 541, 4700, -1000, 441, 441, 243, 514, 441, 4304, 194, + -1000, 4700, 350, -1000, 441, 350, 441, 441, -1000, -1000, + 8016, -1000, -1000, -1000, -1000, 534, 562, 7851, 541, -1000, + 5814, 7686, 752, 4700, -1000, -1000, 4700, 557, -1000, 4700, + -1000, -1000, -1000, -1000, 541, 541, 541, 395, -1000, 752, + -1000, 3295, 2250, -1000, 2250, 7686, -1000, 286, -1000, -1000, + 552, 30, -1000, -1000, -1000, 388, 97, 97, -1000, 284, + 148, -1000, -1000, -1000, 495, -1000, 420, 451, 8016, -1000, + -1000, -1000, 8016, -1000, -1000, -1000, -1000, -1000, 7686, -1000, + -1000, -1000, -1000, -1000, -1000, 19, 1124, 768, -1000, 5076, + 5076, -1000, -1000, 441, 4304, -1000, -1000, 6860, -1000, -1000, + 2877, 4304, 338, -1000, -1000, 123, 275, 123, -142, 560, + 145, -1000, 4700, 336, -1000, -1000, -1000, -1000, -1000, -1000, + 762, 6695, -1000, 718, 539, 408, -1000, -1000, 4107, 350, + 413, 80, 395, 745, 338, 338, 7686, 338, 7686, 7686, + 7686, 5626, 7686, 745, -1000, 2041, -1000, 392, -1000, 544, + -1000, -105, 772, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 277, 250, -1000, 247, 2668, + -1000, -1000, 720, -1000, 5076, 1124, 1124, -1000, -1000, -1000, + -1000, 71, 350, 350, 544, 544, -1000, 544, 555, -1000, + 544, -66, 544, -71, 350, 350, 541, -139, -1000, 338, + 4700, 760, 415, 714, -1000, 541, -1000, -1000, 446, 7686, + 7686, -1000, -1000, 377, -1000, 349, 349, 349, 125, -1000, + -1000, -1000, 7686, -1000, 77, -1000, -123, -1000, 381, 379, + -1000, 541, 1124, 2459, -1000, -1000, -1000, 18, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 5076, 350, 244, 338, + 755, 747, 769, -1000, 541, -1000, 524, 70, -1000, 7686, + -1000, -1000, -1000, -1000, -1000, -1000, 185, 713, -1000, 711, + -1000, -1000, -1000, -40, -1000, -1000, -1000, 37, -1000, -1000, + -1000, 4700, 4700, 7851, 408, 350, 7686, -1000, -1000, 225, + -1000, -1000, 310, -1000, 7686, 350, 17, -151, 338, 403, + 401, -1000, -1000, -1000, -1000, -40, 686, -1000, 663, -146, + -156, -1000, -44, -1000, 659, -1000, -50, -148, 541, -153, + 4888, -157, 224, 350, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 970, 4, 641, 961, 960, 956, 955, 954, 953, - 950, 947, 946, 945, 944, 943, 942, 939, 938, 937, - 172, 936, 933, 929, 45, 928, 65, 922, 920, 27, - 220, 28, 31, 533, 919, 21, 54, 64, 918, 33, - 915, 909, 907, 906, 53, 904, 896, 1197, 895, 894, - 9, 46, 893, 883, 880, 879, 42, 130, 877, 876, - 869, 863, 861, 860, 36, 3, 7, 24, 16, 859, - 26, 6, 856, 41, 855, 854, 853, 852, 15, 848, - 44, 847, 19, 38, 846, 25, 55, 35, 17, 13, - 845, 51, 844, 629, 843, 87, 842, 841, 840, 838, - 837, 836, 23, 129, 497, 11, 29, 834, 831, 1018, - 30, 62, 14, 829, 58, 1036, 22, 828, 827, 20, - 826, 825, 824, 823, 821, 820, 49, 819, 818, 808, - 12, 40, 805, 804, 48, 18, 802, 800, 799, 794, - 50, 792, 37, 788, 787, 786, 32, 34, 783, 10, - 782, 780, 2, 778, 777, 772, 0, 8, 769, 768, - 122, + 0, 1005, 12, 622, 1004, 1002, 1001, 999, 995, 994, + 993, 991, 986, 984, 983, 982, 980, 978, 977, 971, + 76, 970, 968, 965, 44, 962, 57, 960, 959, 30, + 180, 26, 24, 846, 958, 15, 95, 92, 956, 38, + 955, 954, 953, 952, 61, 950, 949, 1114, 947, 946, + 9, 41, 945, 944, 943, 942, 42, 122, 941, 940, + 938, 937, 935, 934, 36, 3, 7, 19, 8, 932, + 139, 21, 931, 34, 927, 926, 924, 923, 23, 920, + 46, 918, 10, 40, 912, 16, 48, 33, 11, 6, + 905, 49, 895, 626, 894, 101, 891, 883, 880, 878, + 875, 873, 25, 307, 477, 45, 29, 871, 856, 1128, + 28, 50, 17, 855, 43, 31, 14, 854, 851, 22, + 849, 845, 844, 840, 839, 837, 90, 836, 834, 833, + 5, 35, 829, 822, 59, 18, 821, 820, 819, 817, + 54, 816, 37, 814, 811, 810, 32, 27, 807, 4, + 804, 803, 2, 802, 801, 792, 0, 20, 791, 790, + 124, } var yyR1 = [...]int{ @@ -1569,7 +1573,7 @@ var yyR1 = [...]int{ 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, @@ -1660,29 +1664,29 @@ var yyChk = [...]int{ 163, 189, 64, 127, 158, 154, 152, 26, 175, 212, 153, 147, 148, 174, 31, 209, 33, 135, 173, 169, 172, 146, 168, 37, 188, 165, 155, 17, 130, 133, - 123, 137, 211, 151, 134, 129, 36, 179, 145, 166, - 136, 156, 157, 171, 144, 167, 138, 180, 213, 164, - 161, 139, 140, 184, 185, 186, 187, 210, 159, 181, - -93, 118, 120, 116, 116, 117, 118, 116, -47, -109, - 55, -103, 118, 116, 105, 163, 111, 182, 117, 31, - 137, -118, 116, 183, 140, 184, 185, 186, 187, 55, - 191, 190, -109, -114, -114, -114, -114, -114, -2, -82, - 16, 15, -5, -3, -156, 6, 19, 20, -26, 38, - 39, -21, -93, -35, -36, -37, -38, -49, -70, -156, - -47, 10, -42, -47, -89, -117, -90, -91, 191, 190, - 189, 163, 188, -71, -104, -109, 55, -103, -144, -140, - 55, 117, -47, 201, -96, 121, 116, -47, -47, -95, - 121, 55, -95, -47, 108, -47, 55, 29, 193, 55, - 137, 116, 138, 118, -115, -156, -105, -104, -102, 70, - 21, 23, 177, 73, 105, 15, 74, 104, 202, 111, - 46, 194, 195, 192, 193, 182, 28, 9, 24, 125, - 20, 98, 113, 77, 78, 128, 22, 126, 68, 18, - 49, 10, 190, 12, 13, 121, 120, 89, 117, 44, - 7, 107, 25, 86, 40, 27, 42, 87, 16, 196, - 197, 30, 206, 132, 100, 47, 34, 71, 66, 50, - 69, 14, 45, 88, 114, 201, 43, 6, 205, 191, - 29, 124, 41, 141, 116, 183, 76, 119, 67, 5, - 122, 8, 48, 51, 198, 199, 200, 32, 142, 75, + 123, 137, 211, 151, 134, 129, 36, 179, 145, 141, + 166, 136, 156, 157, 171, 144, 167, 138, 180, 213, + 164, 161, 142, 139, 140, 184, 185, 186, 187, 210, + 159, 181, -93, 118, 120, 116, 116, 117, 118, 116, + -47, -109, 55, -103, 118, 116, 105, 163, 111, 182, + 117, 31, 137, -118, 116, 183, 140, 184, 185, 186, + 187, 55, 191, 190, -109, -114, -114, -114, -114, -114, + -2, -82, 16, 15, -5, -3, -156, 6, 19, 20, + -26, 38, 39, -21, -93, -35, -36, -37, -38, -49, + -70, -156, -47, 10, -42, -47, -89, -117, -90, -91, + 191, 190, 189, 163, 188, -71, -104, -109, 55, -103, + -144, -140, 55, 117, -47, 201, -96, 121, 116, -47, + -47, -95, 121, 55, -95, -47, 108, -47, 55, 29, + 193, 55, 137, 116, 138, 118, -115, -156, -105, -104, + -102, 70, 21, 23, 177, 73, 105, 15, 74, 104, + 202, 111, 46, 194, 195, 192, 193, 182, 28, 9, + 24, 125, 20, 98, 113, 77, 78, 128, 22, 126, + 68, 18, 49, 10, 190, 12, 13, 121, 120, 89, + 117, 44, 7, 107, 25, 86, 40, 27, 42, 87, + 16, 196, 197, 30, 206, 132, 100, 47, 34, 71, + 66, 50, 69, 14, 45, 88, 114, 201, 43, 6, + 205, 191, 29, 124, 41, 116, 183, 76, 119, 67, + 5, 122, 8, 48, 51, 198, 199, 200, 32, 75, 11, -115, -115, -115, 141, 142, -115, -115, 50, -115, -157, 54, -83, 18, 30, -33, -52, 71, -57, 28, 22, -56, -53, -71, -69, -70, 105, 106, 94, 95, @@ -1768,34 +1772,34 @@ var yyDef = [...]int{ 0, 192, 196, 661, 661, 661, 661, 661, 0, 28, 29, 659, 1, 3, 435, 0, 0, 206, 209, 204, 469, 0, 0, 0, 49, 0, 0, 649, 0, 467, - 488, 489, 492, 493, 592, 593, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, - 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, - 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, - 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, - 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, - 648, 650, 651, 652, 653, 654, 655, 656, 657, 658, - 0, 0, 470, 0, 465, 0, 465, 0, 167, 273, - 496, 497, 649, 0, 0, 0, 0, 662, 662, 662, - 662, 0, 662, 662, 185, 187, 188, 189, 190, 662, - 193, 194, 195, 197, 198, 199, 200, 201, 22, 439, - 0, 0, 427, 24, 0, 202, 207, 208, 212, 210, - 211, 203, 0, 0, 231, 233, 234, 235, 254, 0, - 256, 0, 0, 35, 39, 0, 0, 460, 47, 48, - -2, 598, -2, 0, 409, 0, -2, -2, 0, 55, - 0, 0, 662, 0, 0, 0, 0, 662, 0, 0, - 0, 0, 0, 166, 0, 168, 662, 662, 662, 662, - 662, 662, 662, 662, 177, 663, 664, 494, 495, 500, - 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, - 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, - 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, - 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, - 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, - 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, - 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, - 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, - 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, - 591, 178, 179, 180, 662, 662, 182, 183, 0, 191, + 488, 489, 492, 493, 590, 591, 592, 593, 594, 595, + 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, + 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, + 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, + 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, + 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, + 646, 647, 648, 650, 651, 652, 653, 654, 655, 656, + 657, 658, 0, 0, 470, 0, 465, 0, 465, 0, + 167, 273, 496, 497, 649, 0, 0, 0, 0, 662, + 662, 662, 662, 0, 662, 662, 185, 187, 188, 189, + 190, 662, 193, 194, 195, 197, 198, 199, 200, 201, + 22, 439, 0, 0, 427, 24, 0, 202, 207, 208, + 212, 210, 211, 203, 0, 0, 231, 233, 234, 235, + 254, 0, 256, 0, 0, 35, 39, 0, 0, 460, + 47, 48, -2, 596, -2, 0, 409, 0, -2, -2, + 0, 55, 0, 0, 662, 0, 0, 0, 0, 662, + 0, 0, 0, 0, 0, 166, 0, 168, 662, 662, + 662, 662, 662, 662, 662, 662, 177, 663, 664, 494, + 495, 500, 501, 502, 503, 504, 505, 506, 507, 508, + 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, + 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, + 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, + 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, + 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, + 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, + 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, + 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, + 589, 178, 179, 180, 662, 662, 182, 183, 0, 191, 23, 660, 18, 0, 0, 436, 281, 0, 286, 288, 0, 323, 324, 325, 326, 327, 0, 0, 0, 0, 0, 0, 0, 350, 351, 352, 353, 412, 413, 414, @@ -1805,7 +1809,7 @@ var yyDef = [...]int{ 0, 428, 429, 432, 435, 22, 209, 0, 214, 213, 205, 37, 0, 272, 0, 0, 0, 0, 0, 0, 261, 0, 0, 264, 0, 0, 0, 0, 255, 0, - 22, 0, 275, 627, 257, 0, 259, 260, 37, 0, + 22, 0, 275, 625, 257, 0, 259, 260, 37, 0, 0, 33, 34, 0, 40, 661, 45, 46, 43, 0, 0, 143, 0, 108, 104, 60, 61, 97, 63, 97, 97, 97, 97, 121, 121, 121, 121, 89, 90, 91, diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 8f5e855c815..6f7a612cd23 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -2578,7 +2578,6 @@ reserved_keyword: | SET | SHOW | STRAIGHT_JOIN -| STATUS | TABLE | TABLES | THEN @@ -2593,7 +2592,6 @@ reserved_keyword: | UTC_TIME | UTC_TIMESTAMP | VALUES -| VARIABLES | WHEN | WHERE @@ -2650,6 +2648,7 @@ non_reserved_keyword: | SHARE | SIGNED | SMALLINT +| STATUS | TEXT | THAN | TIME @@ -2662,6 +2661,7 @@ non_reserved_keyword: | UNUSED | VARBINARY | VARCHAR +| VARIABLES | VIEW | VINDEX | VINDEXES diff --git a/go/vt/srvtopo/resilient_server.go b/go/vt/srvtopo/resilient_server.go index 6dcd81e92ed..ed4548f5452 100644 --- a/go/vt/srvtopo/resilient_server.go +++ b/go/vt/srvtopo/resilient_server.go @@ -333,7 +333,7 @@ func (server *ResilientServer) WatchSrvVSchema(ctx context.Context, cell string, } else { for c := range changes { // Note we forward topo.ErrNoNode as is. - callback(nil, c.Err) + callback(c.Value, c.Err) if c.Err != nil { log.Warningf("Error while watching vschema for cell %s (will wait 5s before retrying): %v", cell, c.Err) break diff --git a/go/vt/srvtopo/resilient_server_test.go b/go/vt/srvtopo/resilient_server_test.go index 00e4fab2479..6e93cdfbbbd 100644 --- a/go/vt/srvtopo/resilient_server_test.go +++ b/go/vt/srvtopo/resilient_server_test.go @@ -236,7 +236,7 @@ func TestWatchSrvVSchema(t *testing.T) { // Update value, wait for it. updatedValue := &vschemapb.SrvVSchema{ Keyspaces: map[string]*vschemapb.Keyspace{ - "ks1": {}, + "ks2": {}, }, } if err := ts.UpdateSrvVSchema(ctx, "test_cell", updatedValue); err != nil { diff --git a/go/vt/vtexplain/vtexplain_vttablet.go b/go/vt/vtexplain/vtexplain_vttablet.go index 52696d7db05..7a745386cff 100644 --- a/go/vt/vtexplain/vtexplain_vttablet.go +++ b/go/vt/vtexplain/vtexplain_vttablet.go @@ -216,6 +216,26 @@ func (t *explainTablet) ReadTransaction(ctx context.Context, target *querypb.Tar return t.tsv.ReadTransaction(ctx, target, dtid) } +// ExecuteBatch is part of the QueryService interface. +func (t *explainTablet) ExecuteBatch(ctx context.Context, target *querypb.Target, queries []*querypb.BoundQuery, asTransaction bool, transactionID int64, options *querypb.ExecuteOptions) ([]sqltypes.Result, error) { + t.mu.Lock() + t.currentTime = batchTime.Wait() + + // Since the query is simulated being "sent" over the wire we need to + // copy the bindVars into the executor to avoid a data race. + for _, query := range queries { + bindVariables := sqltypes.CopyBindVariables(query.BindVariables) + t.tabletQueries = append(t.tabletQueries, &TabletQuery{ + Time: t.currentTime, + SQL: query.Sql, + BindVars: bindVariables, + }) + } + t.mu.Unlock() + + return t.tsv.ExecuteBatch(ctx, target, queries, asTransaction, transactionID, options) +} + // BeginExecute is part of the QueryService interface. func (t *explainTablet) BeginExecute(ctx context.Context, target *querypb.Target, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions) (*sqltypes.Result, int64, error) { t.mu.Lock() diff --git a/go/vt/vtgate/autocommit_test.go b/go/vt/vtgate/autocommit_test.go new file mode 100644 index 00000000000..658c4ad313d --- /dev/null +++ b/go/vt/vtgate/autocommit_test.go @@ -0,0 +1,325 @@ +/* +Copyright 2017 Google Inc. + +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 vtgate + +import ( + "testing" + + "golang.org/x/net/context" + + "github.com/youtube/vitess/go/sqltypes" + + querypb "github.com/youtube/vitess/go/vt/proto/query" + vtgatepb "github.com/youtube/vitess/go/vt/proto/vtgate" +) + +// This file contains tests for all the autocommit code paths +// to make sure that single round-trip commits are executed +// correctly whenever possible. + +// TestAutocommitUpdateSharded: instant-commit. +func TestAutocommitUpdateSharded(t *testing.T) { + executor, sbc1, sbc2, _ := createExecutorEnv() + + if _, err := autocommitExec(executor, "update user set a=2 where id = 1"); err != nil { + t.Fatal(err) + } + testBatchQuery(t, "sbc1", sbc1, &querypb.BoundQuery{ + Sql: "update user set a = 2 where id = 1 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{}, + }) + testAsTransactionCount(t, "sbc1", sbc1, 1) + testCommitCount(t, "sbc1", sbc1, 0) + + testBatchQuery(t, "sbc2", sbc2, nil) + testAsTransactionCount(t, "sbc2", sbc2, 0) + testCommitCount(t, "sbc1", sbc1, 0) +} + +// TestAutocommitUpdateLookup: transaction: select before update. +func TestAutocommitUpdateLookup(t *testing.T) { + executor, sbc1, _, sbclookup := createExecutorEnv() + + if _, err := autocommitExec(executor, "update music set a=2 where id = 2"); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: "select user_id from music_user_map where music_id = :music_id", + BindVariables: map[string]*querypb.BindVariable{ + "music_id": sqltypes.Int64BindVariable(2), + }, + }}) + testAsTransactionCount(t, "sbclookup", sbclookup, 0) + testCommitCount(t, "sbclookup", sbclookup, 1) + + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "update music set a = 2 where id = 2 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{}, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 1) +} + +// TestAutocommitUpdateVindexChange: transaction: select & update before final update. +func TestAutocommitUpdateVindexChange(t *testing.T) { + executor, sbc1, _, sbclookup := createExecutorEnv() + + if _, err := autocommitExec(executor, "update user2 set name='myname', lastname='mylastname' where id = 1"); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: "delete from name_lastname_keyspace_id_map where name = :name and lastname = :lastname and keyspace_id = :keyspace_id", + BindVariables: map[string]*querypb.BindVariable{ + "lastname": sqltypes.StringBindVariable("foo"), + "name": sqltypes.Int32BindVariable(1), + "keyspace_id": sqltypes.BytesBindVariable([]byte("\026k@\264J\272K\326")), + }, + }, { + Sql: "insert into name_lastname_keyspace_id_map(name, lastname, keyspace_id) values (:name0, :lastname0, :keyspace_id0)", + BindVariables: map[string]*querypb.BindVariable{ + "name0": sqltypes.BytesBindVariable([]byte("myname")), + "lastname0": sqltypes.BytesBindVariable([]byte("mylastname")), + "keyspace_id0": sqltypes.BytesBindVariable([]byte("\026k@\264J\272K\326")), + }, + }}) + testAsTransactionCount(t, "sbclookup", sbclookup, 0) + testCommitCount(t, "sbclookup", sbclookup, 1) + + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "select name, lastname from user2 where id = 1 for update", + BindVariables: map[string]*querypb.BindVariable{}, + }, { + Sql: "update user2 set name = 'myname', lastname = 'mylastname' where id = 1 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{ + "_name0": sqltypes.BytesBindVariable([]byte("myname")), + "_lastname0": sqltypes.BytesBindVariable([]byte("mylastname")), + }, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 1) +} + +// TestAutocommitDeleteSharded: instant-commit. +func TestAutocommitDeleteSharded(t *testing.T) { + executor, sbc1, sbc2, _ := createExecutorEnv() + + if _, err := autocommitExec(executor, "delete from user_extra where user_id = 1"); err != nil { + t.Fatal(err) + } + testBatchQuery(t, "sbc1", sbc1, &querypb.BoundQuery{ + Sql: "delete from user_extra where user_id = 1 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{}, + }) + testAsTransactionCount(t, "sbc1", sbc1, 1) + testCommitCount(t, "sbc1", sbc1, 0) + + testBatchQuery(t, "sbc2", sbc2, nil) + testAsTransactionCount(t, "sbc2", sbc2, 0) + testCommitCount(t, "sbc1", sbc1, 0) +} + +// TestAutocommitDeleteLookup: transaction: select before update. +func TestAutocommitDeleteLookup(t *testing.T) { + executor, sbc1, _, sbclookup := createExecutorEnv() + + if _, err := autocommitExec(executor, "delete from music where id = 1"); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: "select user_id from music_user_map where music_id = :music_id", + BindVariables: map[string]*querypb.BindVariable{ + "music_id": sqltypes.Int64BindVariable(1), + }, + }, { + Sql: "delete from music_user_map where music_id = :music_id and user_id = :user_id", + BindVariables: map[string]*querypb.BindVariable{ + "music_id": sqltypes.Int32BindVariable(1), + "user_id": sqltypes.Uint64BindVariable(1), + }, + }}) + testAsTransactionCount(t, "sbclookup", sbclookup, 0) + testCommitCount(t, "sbclookup", sbclookup, 1) + + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "select id from music where id = 1 for update", + BindVariables: map[string]*querypb.BindVariable{}, + }, { + Sql: "delete from music where id = 1 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{}, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 1) +} + +// TestAutocommitInsertSharded: instant-commit. +func TestAutocommitInsertSharded(t *testing.T) { + executor, sbc1, sbc2, _ := createExecutorEnv() + + if _, err := autocommitExec(executor, "insert into user_extra(user_id, v) values (1, 2)"); err != nil { + t.Fatal(err) + } + testBatchQuery(t, "sbc1", sbc1, &querypb.BoundQuery{ + Sql: "insert into user_extra(user_id, v) values (:_user_id0, 2) /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{ + "_user_id0": sqltypes.Int64BindVariable(1), + }, + }) + testAsTransactionCount(t, "sbc1", sbc1, 1) + testCommitCount(t, "sbc1", sbc1, 0) + + testBatchQuery(t, "sbc2", sbc2, nil) + testAsTransactionCount(t, "sbc2", sbc2, 0) + testCommitCount(t, "sbc1", sbc1, 0) +} + +// TestAutocommitInsertLookup: transaction: select before update. +func TestAutocommitInsertLookup(t *testing.T) { + executor, sbc1, _, sbclookup := createExecutorEnv() + + if _, err := autocommitExec(executor, "insert into user(id, v, name) values (1, 2, 'myname')"); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: "insert into name_user_map(name, user_id) values (:name0, :user_id0)", + BindVariables: map[string]*querypb.BindVariable{ + "name0": sqltypes.BytesBindVariable([]byte("myname")), + "user_id0": sqltypes.Uint64BindVariable(1), + }, + }}) + testAsTransactionCount(t, "sbclookup", sbclookup, 0) + testCommitCount(t, "sbclookup", sbclookup, 1) + + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "insert into user(id, v, name) values (:_Id0, 2, :_name0) /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{ + "_Id0": sqltypes.Int64BindVariable(1), + "_name0": sqltypes.BytesBindVariable([]byte("myname")), + "__seq0": sqltypes.Int64BindVariable(1), + }, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 1) +} + +func TestAutocommitInsertMultishard(t *testing.T) { + executor, sbc1, sbc2, _ := createExecutorEnv() + + if _, err := autocommitExec(executor, "insert into user_extra(user_id, v) values (1, 2), (3, 4)"); err != nil { + t.Fatal(err) + } + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "insert into user_extra(user_id, v) values (:_user_id0, 2) /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{ + "_user_id0": sqltypes.Int64BindVariable(1), + "_user_id1": sqltypes.Int64BindVariable(3), + }, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 1) + + testQueries(t, "sbc2", sbc2, []*querypb.BoundQuery{{ + Sql: "insert into user_extra(user_id, v) values (:_user_id1, 4) /* vtgate:: keyspace_id:4eb190c9a2fa169c */", + BindVariables: map[string]*querypb.BindVariable{ + "_user_id0": sqltypes.Int64BindVariable(1), + "_user_id1": sqltypes.Int64BindVariable(3), + }, + }}) + testAsTransactionCount(t, "sbc2", sbc2, 0) + testCommitCount(t, "sbc2", sbc2, 1) +} + +// TestAutocommitInsertAutoinc: instant-commit: sequence fetch is not transactional. +func TestAutocommitInsertAutoinc(t *testing.T) { + executor, _, _, sbclookup := createExecutorEnv() + + if _, err := autocommitExec(executor, "insert into main1(id, name) values (null, 'myname')"); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: "select next :n values from user_seq", + BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(1)}, + }}) + testBatchQuery(t, "sbclookup", sbclookup, &querypb.BoundQuery{ + Sql: "insert into main1(id, name) values (:__seq0, 'myname')", + BindVariables: map[string]*querypb.BindVariable{ + "__seq0": sqltypes.Int64BindVariable(1), + }, + }) + testAsTransactionCount(t, "sbclookup", sbclookup, 1) + testCommitCount(t, "sbclookup", sbclookup, 0) +} + +// TestAutocommitTransactionStarted: no instant-commit. +func TestAutocommitTransactionStarted(t *testing.T) { + executor, sbc1, _, _ := createExecutorEnv() + + session := &vtgatepb.Session{ + TargetString: "@master", + Autocommit: true, + InTransaction: true, + TransactionMode: vtgatepb.TransactionMode_MULTI, + } + sql := "update user set a=2 where id = 1" + + if _, err := executor.Execute(context.Background(), "TestExecute", NewSafeSession(session), sql, map[string]*querypb.BindVariable{}); err != nil { + t.Fatal(err) + } + + testQueries(t, "sbc1", sbc1, []*querypb.BoundQuery{{ + Sql: "update user set a = 2 where id = 1 /* vtgate:: keyspace_id:166b40b44aba4bd6 */", + BindVariables: map[string]*querypb.BindVariable{}, + }}) + testAsTransactionCount(t, "sbc1", sbc1, 0) + testCommitCount(t, "sbc1", sbc1, 0) +} + +// TestAutocommitDirectTarget: no instant-commit. +func TestAutocommitDirectTarget(t *testing.T) { + executor, _, _, sbclookup := createExecutorEnv() + + session := &vtgatepb.Session{ + TargetString: "TestUnsharded/0@master", + Autocommit: true, + TransactionMode: vtgatepb.TransactionMode_MULTI, + } + sql := "insert into simple(val) values ('val')" + + if _, err := executor.Execute(context.Background(), "TestExecute", NewSafeSession(session), sql, map[string]*querypb.BindVariable{}); err != nil { + t.Error(err) + } + testQueries(t, "sbclookup", sbclookup, []*querypb.BoundQuery{{ + Sql: sql + "/* vtgate:: filtered_replication_unfriendly */", + BindVariables: map[string]*querypb.BindVariable{}, + }}) + testAsTransactionCount(t, "sbclookup", sbclookup, 0) + testCommitCount(t, "sbclookup", sbclookup, 1) +} + +func autocommitExec(executor *Executor, sql string) (*sqltypes.Result, error) { + session := &vtgatepb.Session{ + TargetString: "@master", + Autocommit: true, + TransactionMode: vtgatepb.TransactionMode_MULTI, + } + + return executor.Execute(context.Background(), "TestExecute", NewSafeSession(session), sql, map[string]*querypb.BindVariable{}) +} diff --git a/go/vt/vtgate/engine/merge_sort_test.go b/go/vt/vtgate/engine/merge_sort_test.go index 5bdd050899a..bd900acb14a 100644 --- a/go/vt/vtgate/engine/merge_sort_test.go +++ b/go/vt/vtgate/engine/merge_sort_test.go @@ -342,7 +342,7 @@ func (t *fakeVcursor) Execute(method string, query string, bindvars map[string]* panic("unimplemented") } -func (t *fakeVcursor) ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML bool) (*sqltypes.Result, error) { +func (t *fakeVcursor) ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, error) { panic("unimplemented") } diff --git a/go/vt/vtgate/engine/primitive.go b/go/vt/vtgate/engine/primitive.go index 938a91ca553..07458c30ad7 100644 --- a/go/vt/vtgate/engine/primitive.go +++ b/go/vt/vtgate/engine/primitive.go @@ -43,7 +43,7 @@ type VCursor interface { // Context returns the context of the current request. Context() context.Context Execute(method string, query string, bindvars map[string]*querypb.BindVariable, isDML bool) (*sqltypes.Result, error) - ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML bool) (*sqltypes.Result, error) + ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, error) ExecuteStandalone(query string, bindvars map[string]*querypb.BindVariable, keyspace, shard string) (*sqltypes.Result, error) StreamExecuteMulti(query string, keyspace string, shardVars map[string]map[string]*querypb.BindVariable, callback func(reply *sqltypes.Result) error) error GetKeyspaceShards(vkeyspace *vindexes.Keyspace) (string, []*topodatapb.ShardReference, error) diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 67a0d3c4737..1e51e73ef1e 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -333,7 +333,8 @@ func (route *Route) execute(vcursor VCursor, bindVars, joinVars map[string]*quer } shardQueries := route.getShardQueries(route.Query, params) - result, err := vcursor.ExecuteMultiShard(params.ks, shardQueries, isDML) + // canAutocommit should be true only if it's a DML. + result, err := vcursor.ExecuteMultiShard(params.ks, shardQueries, isDML, isDML /* canAutocommit */) if err != nil { return nil, err } @@ -388,7 +389,7 @@ func (route *Route) GetFields(vcursor VCursor, bindVars, joinVars map[string]*qu return nil, err } - qr, err := route.execShard(vcursor, route.FieldQuery, bindVars, ks, shard, false /* isDML */) + qr, err := route.execShard(vcursor, route.FieldQuery, bindVars, ks, shard, false /* isDML */, false /* canAutocommit */) if err != nil { return nil, err } @@ -467,7 +468,7 @@ func (route *Route) execUpdateEqual(vcursor VCursor, bindVars map[string]*queryp return result, nil } rewritten := sqlannotation.AddKeyspaceIDs(route.Query, [][]byte{ksid}, "") - return route.execShard(vcursor, rewritten, bindVars, ks, shard, true /* isDML */) + return route.execShard(vcursor, rewritten, bindVars, ks, shard, true /* isDML */, true /* canAutocommit */) } // execUpdateEqualChangedVindex performs an update when a vindex is being modified @@ -494,7 +495,7 @@ func (route *Route) execUpdateEqualChangedVindex(vcursor VCursor, query string, var err error rewritten := sqlannotation.AddKeyspaceIDs(route.Query, [][]byte{keyspaceID}, "") if route.Subquery != "" { - subQueryResult, err = route.execShard(vcursor, route.Subquery, bindVars, keyspace, shard, false /* isDML */) + subQueryResult, err = route.execShard(vcursor, route.Subquery, bindVars, keyspace, shard, false /* isDML */, false /* canAutocommit */) if err != nil { return nil, vterrors.Wrap(err, "execUpdateEqual") } @@ -503,7 +504,7 @@ func (route *Route) execUpdateEqualChangedVindex(vcursor VCursor, query string, if err != nil { return nil, vterrors.Wrap(err, "execUpdateEqual") } - result, err := route.execShard(vcursor, rewritten, bindVars, keyspace, shard, true /* isDML */) + result, err := route.execShard(vcursor, rewritten, bindVars, keyspace, shard, true /* isDML */, true /* canAutocommit */) if err != nil { return nil, vterrors.Wrap(err, "execUpdateEqual") } @@ -529,7 +530,7 @@ func (route *Route) execDeleteEqual(vcursor VCursor, bindVars map[string]*queryp } } rewritten := sqlannotation.AddKeyspaceIDs(route.Query, [][]byte{ksid}, "") - return route.execShard(vcursor, rewritten, bindVars, ks, shard, true /* isDML */) + return route.execShard(vcursor, rewritten, bindVars, ks, shard, true /* isDML */, true /* canAutocommit */) } func (route *Route) execInsertUnsharded(vcursor VCursor, bindVars map[string]*querypb.BindVariable) (*sqltypes.Result, error) { @@ -543,7 +544,7 @@ func (route *Route) execInsertUnsharded(vcursor VCursor, bindVars map[string]*qu } shardQueries := route.getShardQueries(route.Query, params) - result, err := vcursor.ExecuteMultiShard(params.ks, shardQueries, true /* isDML */) + result, err := vcursor.ExecuteMultiShard(params.ks, shardQueries, true /* isDML */, true /* canAutocommit */) if err != nil { return nil, vterrors.Wrap(err, "execInsertUnsharded") } @@ -568,7 +569,7 @@ func (route *Route) execInsertSharded(vcursor VCursor, bindVars map[string]*quer return nil, vterrors.Wrap(err, "execInsertSharded") } - result, err := vcursor.ExecuteMultiShard(keyspace, shardQueries, true /* isDML */) + result, err := vcursor.ExecuteMultiShard(keyspace, shardQueries, true /* isDML */, true /* canAutocommit */) if err != nil { return nil, vterrors.Wrap(err, "execInsertSharded") } @@ -689,7 +690,7 @@ func (route *Route) updateChangedVindexes(subQueryResult *sqltypes.Result, vcurs } func (route *Route) deleteVindexEntries(vcursor VCursor, bindVars map[string]*querypb.BindVariable, ks, shard string, ksid []byte) error { - result, err := route.execShard(vcursor, route.Subquery, bindVars, ks, shard, false /* isDML */) + result, err := route.execShard(vcursor, route.Subquery, bindVars, ks, shard, false /* isDML */, false /* canAutocommit */) if err != nil { return err } @@ -1080,13 +1081,13 @@ func (route *Route) execAnyShard(vcursor VCursor, bindVars map[string]*querypb.B return vcursor.ExecuteStandalone(route.Query, bindVars, ks, shard) } -func (route *Route) execShard(vcursor VCursor, query string, bindVars map[string]*querypb.BindVariable, keyspace, shard string, isDML bool) (*sqltypes.Result, error) { +func (route *Route) execShard(vcursor VCursor, query string, bindVars map[string]*querypb.BindVariable, keyspace, shard string, isDML, canAutocommit bool) (*sqltypes.Result, error) { return vcursor.ExecuteMultiShard(keyspace, map[string]*querypb.BoundQuery{ shard: { Sql: query, BindVariables: bindVars, }, - }, isDML) + }, isDML, canAutocommit) } func (route *Route) anyShard(vcursor VCursor, keyspace *vindexes.Keyspace) (string, string, error) { diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 89b990b0909..c41576bb664 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -166,6 +166,16 @@ func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql st defer e.txConn.Rollback(ctx, safeSession) } + // The SetAutocommitable flag should be same as mustCommit. + // If we started a transaction because of autocommit, then mustCommit + // will be true, which means that we can autocommit. If we were already + // in a transaction, it means that the app started it, or we are being + // called recursively. If so, we cannot autocommit because whatever we + // do is likely not final. + // The control flow is such that autocommitable can only be turned on + // at the beginning, but never after. + safeSession.SetAutocommitable(mustCommit) + qr, err := e.handleExec(ctx, safeSession, sql, bindVars, target, logStats) if err != nil { return nil, err @@ -195,6 +205,8 @@ func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql st return e.handleUse(ctx, safeSession, sql, bindVars) case sqlparser.StmtOther: return e.handleOther(ctx, safeSession, sql, bindVars, target, logStats) + case sqlparser.StmtComment: + return e.handleComment(ctx, safeSession, sql, bindVars, target, logStats) } return nil, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unrecognized statement: %s", sql) } @@ -202,6 +214,8 @@ func (e *Executor) execute(ctx context.Context, safeSession *SafeSession, sql st func (e *Executor) handleExec(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, target querypb.Target, logStats *LogStats) (*sqltypes.Result, error) { if target.Shard != "" { // V1 mode or V3 mode with a forced shard target + // TODO(sougou): change this flow to go through V3 functions + // which will allow us to benefit from the autocommitable flag. sql = sqlannotation.AnnotateIfDML(sql, nil) if e.normalize { @@ -705,6 +719,13 @@ func (e *Executor) handleOther(ctx context.Context, safeSession *SafeSession, sq return result, err } +func (e *Executor) handleComment(ctx context.Context, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, target querypb.Target, logStats *LogStats) (*sqltypes.Result, error) { + _, sql = sqlparser.ExtractMysqlComment(sql) + + // Not sure if this is a good idea. + return &sqltypes.Result{}, nil +} + // StreamExecute executes a streaming query. func (e *Executor) StreamExecute(ctx context.Context, method string, safeSession *SafeSession, sql string, bindVars map[string]*querypb.BindVariable, target querypb.Target, callback func(*sqltypes.Result) error) (err error) { logStats := NewLogStats(ctx, method, sql, bindVars) diff --git a/go/vt/vtgate/executor_framework_test.go b/go/vt/vtgate/executor_framework_test.go index 4a70de283d3..2f6fb6af06d 100644 --- a/go/vt/vtgate/executor_framework_test.go +++ b/go/vt/vtgate/executor_framework_test.go @@ -18,6 +18,7 @@ package vtgate import ( "fmt" + "reflect" "strconv" "strings" "testing" @@ -309,6 +310,40 @@ func executorStream(executor *Executor, sql string) (qr *sqltypes.Result, err er return qr, nil } +// testBatchQuery verifies that a single (or no) query ExecuteBatch was performed on the SandboxConn. +func testBatchQuery(t *testing.T, sbcName string, sbc *sandboxconn.SandboxConn, boundQuery *querypb.BoundQuery) { + t.Helper() + + var wantQueries [][]*querypb.BoundQuery + if boundQuery != nil { + wantQueries = [][]*querypb.BoundQuery{{boundQuery}} + } + if !reflect.DeepEqual(sbc.BatchQueries, wantQueries) { + t.Errorf("%s.BatchQueries:\n%+v, want\n%+v\n", sbcName, sbc.BatchQueries, wantQueries) + } +} + +func testAsTransactionCount(t *testing.T, sbcName string, sbc *sandboxconn.SandboxConn, want int) { + t.Helper() + if got, want := sbc.AsTransactionCount.Get(), int64(want); got != want { + t.Errorf("%s.AsTransactionCount: %d, want %d\n", sbcName, got, want) + } +} + +func testQueries(t *testing.T, sbcName string, sbc *sandboxconn.SandboxConn, wantQueries []*querypb.BoundQuery) { + t.Helper() + if !reflect.DeepEqual(sbc.Queries, wantQueries) { + t.Errorf("%s.Queries:\n%+v, want\n%+v\n", sbcName, sbc.Queries, wantQueries) + } +} + +func testCommitCount(t *testing.T, sbcName string, sbc *sandboxconn.SandboxConn, want int) { + t.Helper() + if got, want := sbc.CommitCount.Get(), int64(want); got != want { + t.Errorf("%s.CommitCount: %d, want %d\n", sbcName, got, want) + } +} + func testNonZeroDuration(t *testing.T, what, d string) { t.Helper() time, _ := strconv.ParseFloat(d, 64) diff --git a/go/vt/vtgate/executor_test.go b/go/vt/vtgate/executor_test.go index 15a249c5a16..ee88a509c20 100644 --- a/go/vt/vtgate/executor_test.go +++ b/go/vt/vtgate/executor_test.go @@ -385,7 +385,9 @@ func TestExecutorAutocommit(t *testing.T) { t.Errorf("Commit count: %d, want %d", got, want) } - startCount = sbclookup.CommitCount.Get() + // In the following section, we look at AsTransaction count instead of CommitCount because + // the update results in a single round-trip ExecuteBatch call. + startCount = sbclookup.AsTransactionCount.Get() _, err = executor.Execute(context.Background(), "TestExecute", session, "update main1 set id=1", nil) if err != nil { t.Fatal(err) @@ -394,7 +396,7 @@ func TestExecutorAutocommit(t *testing.T) { if !proto.Equal(session.Session, wantSession) { t.Errorf("autocommit=1: %v, want %v", session.Session, wantSession) } - if got, want := sbclookup.CommitCount.Get(), startCount+1; got != want { + if got, want := sbclookup.AsTransactionCount.Get(), startCount+1; got != want { t.Errorf("Commit count: %d, want %d", got, want) } @@ -407,6 +409,7 @@ func TestExecutorAutocommit(t *testing.T) { } // autocommit = 1, "begin" + session.Reset() startCount = sbclookup.CommitCount.Get() _, err = executor.Execute(context.Background(), "TestExecute", session, "begin", nil) if err != nil { @@ -734,6 +737,26 @@ func TestExecutorUse(t *testing.T) { } } +func TestExecutorComment(t *testing.T) { + executor, _, _, _ := createExecutorEnv() + + stmts := []string{ + "/*! SET max_execution_time=5000*/", + "/*!50708 SET max_execution_time=5000*/", + } + wantResult := &sqltypes.Result{} + + for _, stmt := range stmts { + gotResult, err := executor.Execute(context.Background(), "TestExecute", NewSafeSession(&vtgatepb.Session{TargetString: KsTestUnsharded}), stmt, nil) + if err != nil { + t.Error(err) + } + if !reflect.DeepEqual(gotResult, wantResult) { + t.Errorf("Exec %s: %v, want %v", stmt, gotResult, wantResult) + } + } +} + func TestExecutorOther(t *testing.T) { executor, sbc1, sbc2, sbclookup := createExecutorEnv() diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index e829296e869..629676cf24e 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -32,11 +32,36 @@ import ( // (the use pattern is 'Find', if not found, then 'Append', // for a single shard) type SafeSession struct { - mu sync.Mutex - mustRollback bool + mu sync.Mutex + mustRollback bool + autocommitState autocommitState *vtgatepb.Session } +// autocommitState keeps track of whether a single round-trip +// commit to vttablet is possible. It starts as autocommitable +// if we started a transaction because of the autocommit flag +// being set. Otherwise, it starts as notAutocommitable. +// If execute is recursively called using the same session, +// like from a vindex, we will already be in a transaction, +// and this should cause the state to become notAutocommitable. +// +// SafeSession lets you request a commit token, which will +// be issued if the state is autocommitable, and ShardSessions +// is empty, implying that no intermediate transactions were started. +// If so, the state transitions to autocommited, which is terminal. +// If the token is succesfully issued, the caller has to perform +// the commit. If a token cannot be issued, then a traditional +// commit has to be performed at the outermost level where +// the autocommitable transition happened. +type autocommitState int + +const ( + notAutocommittable = autocommitState(iota) + autocommittable + autocommitted +) + // NewSafeSession returns a new SafeSession based on the Session func NewSafeSession(sessn *vtgatepb.Session) *SafeSession { return &SafeSession{Session: sessn} @@ -52,6 +77,41 @@ func NewAutocommitSession(sessn *vtgatepb.Session) *SafeSession { return NewSafeSession(newSession) } +// SetAutocommitable sets the state to autocommitable if true. +// Otherwise, it's notAutocommitable. +func (session *SafeSession) SetAutocommitable(flag bool) { + session.mu.Lock() + defer session.mu.Unlock() + + if session.autocommitState == autocommitted { + panic("BUG: SetAutocommitable: unexpected autocommit state") + } + + if flag { + session.autocommitState = autocommittable + } else { + session.autocommitState = notAutocommittable + } +} + +// AutocommitApproval returns true if we can perform a single round-trip +// autocommit. If so, the caller is responsible for commiting their +// transaction. +func (session *SafeSession) AutocommitApproval() bool { + session.mu.Lock() + defer session.mu.Unlock() + + if session.autocommitState == autocommitted { + panic("BUG: AutocommitToken: unexpected autocommit state") + } + + if session.autocommitState == autocommittable && len(session.ShardSessions) == 0 { + session.autocommitState = autocommitted + return true + } + return false +} + // InTransaction returns true if we are in a transaction func (session *SafeSession) InTransaction() bool { if session == nil || session.Session == nil { @@ -81,6 +141,11 @@ func (session *SafeSession) Find(keyspace, shard string, tabletType topodatapb.T func (session *SafeSession) Append(shardSession *vtgatepb.Session_ShardSession, txMode vtgatepb.TransactionMode) error { session.mu.Lock() defer session.mu.Unlock() + + if session.autocommitState == autocommitted { + panic("BUG: SafeSession.Append: unexpected autocommit state") + } + // Always append, in order for rollback to succeed. session.ShardSessions = append(session.ShardSessions, shardSession) if session.isSingleDB(txMode) && len(session.ShardSessions) > 1 { @@ -124,6 +189,8 @@ func (session *SafeSession) Reset() { } session.mu.Lock() defer session.mu.Unlock() + session.mustRollback = false + session.autocommitState = notAutocommittable session.Session.InTransaction = false session.SingleDb = false session.ShardSessions = nil diff --git a/go/vt/vtgate/scatter_conn.go b/go/vt/vtgate/scatter_conn.go index ca17e1b26c1..167102652d8 100644 --- a/go/vt/vtgate/scatter_conn.go +++ b/go/vt/vtgate/scatter_conn.go @@ -166,6 +166,7 @@ func (stc *ScatterConn) ExecuteMultiShard( tabletType topodatapb.TabletType, session *SafeSession, notInTransaction bool, + canAutocommit bool, ) (*sqltypes.Result, error) { // mu protects qr @@ -176,6 +177,8 @@ func (stc *ScatterConn) ExecuteMultiShard( shards = append(shards, shard) } + canCommit := len(shards) == 1 && canAutocommit && session.AutocommitApproval() + err := stc.multiGoTransaction( ctx, "Execute", @@ -185,23 +188,25 @@ func (stc *ScatterConn) ExecuteMultiShard( session, notInTransaction, func(target *querypb.Target, shouldBegin bool, transactionID int64) (int64, error) { - var innerqr *sqltypes.Result - var opts *querypb.ExecuteOptions + var ( + innerqr *sqltypes.Result + err error + opts *querypb.ExecuteOptions + ) if session != nil && session.Session != nil { opts = session.Session.Options } - if shouldBegin { - var err error + + switch { + case canCommit: + innerqr, err = stc.executeAutocommit(ctx, target, shardQueries[target.Shard].Sql, shardQueries[target.Shard].BindVariables, opts) + case shouldBegin: innerqr, transactionID, err = stc.gateway.BeginExecute(ctx, target, shardQueries[target.Shard].Sql, shardQueries[target.Shard].BindVariables, opts) - if err != nil { - return transactionID, err - } - } else { - var err error + default: innerqr, err = stc.gateway.Execute(ctx, target, shardQueries[target.Shard].Sql, shardQueries[target.Shard].BindVariables, transactionID, opts) - if err != nil { - return transactionID, err - } + } + if err != nil { + return transactionID, err } mu.Lock() @@ -212,6 +217,20 @@ func (stc *ScatterConn) ExecuteMultiShard( return qr, err } +func (stc *ScatterConn) executeAutocommit(ctx context.Context, target *querypb.Target, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions) (*sqltypes.Result, error) { + queries := []*querypb.BoundQuery{{ + Sql: sql, + BindVariables: bindVariables, + }} + // ExecuteBatch is a stop-gap because it's the only function that can currently do + // single round-trip commit. + qrs, err := stc.gateway.ExecuteBatch(ctx, target, queries, true /* asTransaction */, 0, options) + if err != nil { + return nil, err + } + return &qrs[0], nil +} + // ExecuteEntityIds executes queries that are shard specific. func (stc *ScatterConn) ExecuteEntityIds( ctx context.Context, diff --git a/go/vt/vtgate/scatter_conn_test.go b/go/vt/vtgate/scatter_conn_test.go index b054162372c..a7cd74e44a2 100644 --- a/go/vt/vtgate/scatter_conn_test.go +++ b/go/vt/vtgate/scatter_conn_test.go @@ -57,7 +57,7 @@ func TestScatterConnExecuteMulti(t *testing.T) { shardQueries[shard] = query } - return sc.ExecuteMultiShard(context.Background(), "TestScatterConnExecuteMultiShard", shardQueries, topodatapb.TabletType_REPLICA, nil, false) + return sc.ExecuteMultiShard(context.Background(), "TestScatterConnExecuteMultiShard", shardQueries, topodatapb.TabletType_REPLICA, nil, false, false) }) } @@ -249,7 +249,7 @@ func TestMultiExecs(t *testing.T) { shardQueries[shard] = query } - _, _ = sc.ExecuteMultiShard(context.Background(), "TestMultiExecs", shardQueries, topodatapb.TabletType_REPLICA, nil, false) + _, _ = sc.ExecuteMultiShard(context.Background(), "TestMultiExecs", shardQueries, topodatapb.TabletType_REPLICA, nil, false, false) if len(sbc0.Queries) == 0 || len(sbc1.Queries) == 0 { t.Fatalf("didn't get expected query") } diff --git a/go/vt/vtgate/vcursor_impl.go b/go/vt/vtgate/vcursor_impl.go index e3d92f74c77..a2e642e22f3 100644 --- a/go/vt/vtgate/vcursor_impl.go +++ b/go/vt/vtgate/vcursor_impl.go @@ -110,9 +110,9 @@ func (vc *vcursorImpl) Execute(method string, query string, BindVars map[string] } // ExecuteMultiShard executes different queries on different shards and returns the combined result. -func (vc *vcursorImpl) ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML bool) (*sqltypes.Result, error) { +func (vc *vcursorImpl) ExecuteMultiShard(keyspace string, shardQueries map[string]*querypb.BoundQuery, isDML, canAutocommit bool) (*sqltypes.Result, error) { atomic.AddUint32(&vc.logStats.ShardQueries, uint32(len(shardQueries))) - qr, err := vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, keyspace, commentedShardQueries(shardQueries, vc.trailingComments), vc.target.TabletType, vc.safeSession, false) + qr, err := vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, keyspace, commentedShardQueries(shardQueries, vc.trailingComments), vc.target.TabletType, vc.safeSession, false, canAutocommit) if err == nil { vc.hasPartialDML = true } @@ -127,7 +127,9 @@ func (vc *vcursorImpl) ExecuteStandalone(query string, BindVars map[string]*quer BindVariables: BindVars, }, } - return vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, keyspace, bq, vc.target.TabletType, NewAutocommitSession(vc.safeSession.Session), false) + // The canAutocommit flag is not significant because we currently don't execute DMLs through ExecuteStandalone. + // But we set it to true for future-proofing this function. + return vc.executor.scatterConn.ExecuteMultiShard(vc.ctx, keyspace, bq, vc.target.TabletType, NewAutocommitSession(vc.safeSession.Session), false, true /* canAutocommit */) } // StreamExeculteMulti is the streaming version of ExecuteMultiShard. diff --git a/go/vt/vttablet/tabletserver/planbuilder/dml.go b/go/vt/vttablet/tabletserver/planbuilder/dml.go index f8863f4bc56..39f4b874411 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/dml.go +++ b/go/vt/vttablet/tabletserver/planbuilder/dml.go @@ -32,6 +32,10 @@ func analyzeUpdate(upd *sqlparser.Update, tables map[string]*schema.Table) (plan FullQuery: GenerateFullQuery(upd), } + if PassthroughDMLs { + return plan, nil + } + if len(upd.TableExprs) > 1 { plan.Reason = ReasonMultiTable return plan, nil @@ -95,6 +99,10 @@ func analyzeDelete(del *sqlparser.Delete, tables map[string]*schema.Table) (plan FullQuery: GenerateFullQuery(del), } + if PassthroughDMLs { + return plan, nil + } + if len(del.TableExprs) > 1 { plan.Reason = ReasonMultiTable return plan, nil @@ -292,6 +300,10 @@ func analyzeInsert(ins *sqlparser.Insert, tables map[string]*schema.Table) (plan PlanID: PlanPassDML, FullQuery: GenerateFullQuery(ins), } + if PassthroughDMLs { + return plan, nil + } + if ins.Action == sqlparser.ReplaceStr { plan.Reason = ReasonReplace return plan, nil diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index d76326d92d3..8f20563c53f 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -32,6 +32,9 @@ var ( // ErrTooComplex indicates given sql query is too complex. ErrTooComplex = vterrors.New(vtrpcpb.Code_INVALID_ARGUMENT, "Complex") execLimit = &sqlparser.Limit{Rowcount: sqlparser.NewValArg([]byte(":#maxLimit"))} + + // PassthroughDMLs will return PlanPassDML for all update or delete statements + PassthroughDMLs = false ) //_______________________________________________ @@ -49,6 +52,9 @@ const ( PlanNextval // PlanPassDML is pass through update & delete statements. This is // the default plan for update and delete statements. + // If PassthroughDMLs is true, then it is used for all DML statements + // and is valid in all replication modes. + // Otherwise is only allowed in row based replication mode PlanPassDML // PlanDMLPK is an update or delete with an equality where clause(s) // on primary key(s). diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan_test.go b/go/vt/vttablet/tabletserver/planbuilder/plan_test.go index 211cd3fed1f..78577f3137d 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan_test.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan_test.go @@ -76,7 +76,12 @@ func toJSON(p *Plan) ([]byte, error) { func TestPlan(t *testing.T) { testSchema := loadSchema("schema_test.json") for tcase := range iterateExecFile("exec_cases.txt") { + if strings.Contains(tcase.options, "PassthroughDMLs") { + PassthroughDMLs = true + } plan, err := Build(tcase.input, testSchema) + PassthroughDMLs = false + var out string if err != nil { out = err.Error() @@ -232,10 +237,11 @@ func loadSchema(name string) map[string]*schema.Table { } type testCase struct { - file string - lineno int - input string - output string + file string + lineno int + options string + input string + output string } func iterateExecFile(name string) (testCaseIterator chan testCase) { @@ -250,6 +256,7 @@ func iterateExecFile(name string) (testCaseIterator chan testCase) { r := bufio.NewReader(fd) lineno := 0 + options := "" for { binput, err := r.ReadBytes('\n') if err != nil { @@ -265,6 +272,11 @@ func iterateExecFile(name string) (testCaseIterator chan testCase) { //fmt.Printf("%s\n", input) continue } + + if strings.HasPrefix(input, "options:") { + options = input[8:] + continue + } err = json.Unmarshal(binput, &input) if err != nil { fmt.Printf("Line: %d, input: %s\n", lineno, binput) @@ -293,7 +305,8 @@ func iterateExecFile(name string) (testCaseIterator chan testCase) { break } } - testCaseIterator <- testCase{name, lineno, input, string(output)} + testCaseIterator <- testCase{name, lineno, options, input, string(output)} + options = "" } }() return testCaseIterator diff --git a/go/vt/vttablet/tabletserver/query_engine.go b/go/vt/vttablet/tabletserver/query_engine.go index d304ef50733..e5c1461e8ac 100644 --- a/go/vt/vttablet/tabletserver/query_engine.go +++ b/go/vt/vttablet/tabletserver/query_engine.go @@ -135,6 +135,8 @@ type QueryEngine struct { maxResultSize sync2.AtomicInt64 warnResultSize sync2.AtomicInt64 maxDMLRows sync2.AtomicInt64 + passthroughDMLs sync2.AtomicBool + allowUnsafeDMLs bool streamBufferSize sync2.AtomicInt64 // tableaclExemptCount count the number of accesses allowed // based on membership in the superuser ACL @@ -209,6 +211,9 @@ func NewQueryEngine(checker connpool.MySQLChecker, se *schema.Engine, config tab qe.maxDMLRows = sync2.NewAtomicInt64(int64(config.MaxDMLRows)) qe.streamBufferSize = sync2.NewAtomicInt64(int64(config.StreamBufferSize)) + qe.passthroughDMLs = sync2.NewAtomicBool(config.PassthroughDMLs) + planbuilder.PassthroughDMLs = config.PassthroughDMLs + qe.accessCheckerLogger = logutil.NewThrottledLogger("accessChecker", 1*time.Second) qeOnce.Do(func() { diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index d4270158fc7..faf8a2fb2d2 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -121,7 +121,7 @@ func (qre *QueryExecutor) Execute() (reply *sqltypes.Result, err error) { defer conn.Recycle() switch qre.plan.PlanID { case planbuilder.PlanPassDML: - if qre.tsv.qe.binlogFormat != connpool.BinlogFormatRow { + if !qre.tsv.qe.allowUnsafeDMLs && (qre.tsv.qe.binlogFormat != connpool.BinlogFormatRow) { return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cannot identify primary key of statement") } return qre.txFetch(conn, qre.plan.FullQuery, qre.bindVars, nil, nil, false, true) @@ -259,7 +259,7 @@ func (qre *QueryExecutor) execDmlAutoCommit() (reply *sqltypes.Result, err error return qre.execAsTransaction(func(conn *TxConnection) (reply *sqltypes.Result, err error) { switch qre.plan.PlanID { case planbuilder.PlanPassDML: - if qre.tsv.qe.binlogFormat != connpool.BinlogFormatRow { + if !qre.tsv.qe.allowUnsafeDMLs && (qre.tsv.qe.binlogFormat != connpool.BinlogFormatRow) { return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "unsupported: cannot identify primary key of statement") } reply, err = qre.txFetch(conn, qre.plan.FullQuery, qre.bindVars, nil, nil, false, true) diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index fe39ec1772e..031a54e3575 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -105,6 +105,62 @@ func TestQueryExecutorPlanPassDmlRBR(t *testing.T) { testCommitHelper(t, tsv, qre) } +func TestQueryExecutorPassthroughDml(t *testing.T) { + db := setUpQueryExecutorTest(t) + defer db.Close() + planbuilder.PassthroughDMLs = true + defer func() { planbuilder.PassthroughDMLs = false }() + query := "update test_table set pk = foo()" + want := &sqltypes.Result{} + db.AddQuery(query, want) + ctx := context.Background() + // RBR mode + tsv := newTestTabletServer(ctx, noFlags, db) + defer tsv.StopService() + + planbuilder.PassthroughDMLs = true + defer func() { planbuilder.PassthroughDMLs = false }() + tsv.qe.passthroughDMLs.Set(true) + tsv.qe.binlogFormat = connpool.BinlogFormatRow + + txid := newTransaction(tsv, nil) + qre := newTestQueryExecutor(ctx, tsv, query, txid) + + checkPlanID(t, planbuilder.PlanPassDML, qre.plan.PlanID) + got, err := qre.Execute() + if err != nil { + t.Fatalf("qre.Execute() = %v, want nil", err) + } + if !reflect.DeepEqual(got, want) { + t.Fatalf("got: %v, want: %v", got, want) + } + wantqueries := []string{query} + gotqueries := fetchRecordedQueries(qre) + if !reflect.DeepEqual(gotqueries, wantqueries) { + t.Errorf("queries: %v, want %v", gotqueries, wantqueries) + } + + // Statement mode also works when allowUnsafeDMLs is true + tsv.qe.binlogFormat = connpool.BinlogFormatStatement + _, err = qre.Execute() + if code := vterrors.Code(err); code != vtrpcpb.Code_UNIMPLEMENTED { + t.Errorf("qre.Execute: %v, want %v", code, vtrpcpb.Code_INVALID_ARGUMENT) + } + + tsv.qe.allowUnsafeDMLs = true + got, err = qre.Execute() + if !reflect.DeepEqual(got, want) { + t.Fatalf("got: %v, want: %v", got, want) + } + wantqueries = []string{query, query} + gotqueries = fetchRecordedQueries(qre) + if !reflect.DeepEqual(gotqueries, wantqueries) { + t.Errorf("queries: %v, want %v", gotqueries, wantqueries) + } + + testCommitHelper(t, tsv, qre) +} + func TestQueryExecutorPlanPassDmlAutoCommitRBR(t *testing.T) { db := setUpQueryExecutorTest(t) defer db.Close() @@ -134,6 +190,49 @@ func TestQueryExecutorPlanPassDmlAutoCommitRBR(t *testing.T) { } } +func TestQueryExecutorPassthroughDmlAutoCommit(t *testing.T) { + db := setUpQueryExecutorTest(t) + defer db.Close() + query := "update test_table set pk = foo()" + want := &sqltypes.Result{} + db.AddQuery(query, want) + ctx := context.Background() + // RBR mode + tsv := newTestTabletServer(ctx, noFlags, db) + defer tsv.StopService() + + planbuilder.PassthroughDMLs = true + defer func() { planbuilder.PassthroughDMLs = false }() + tsv.qe.passthroughDMLs.Set(true) + tsv.qe.binlogFormat = connpool.BinlogFormatRow + + qre := newTestQueryExecutor(ctx, tsv, query, 0) + checkPlanID(t, planbuilder.PlanPassDML, qre.plan.PlanID) + got, err := qre.Execute() + if err != nil { + t.Fatalf("qre.Execute() = %v, want nil", err) + } + if !reflect.DeepEqual(got, want) { + t.Fatalf("got: %v, want: %v", got, want) + } + + // Statement mode + tsv.qe.binlogFormat = connpool.BinlogFormatStatement + _, err = qre.Execute() + if code := vterrors.Code(err); code != vtrpcpb.Code_UNIMPLEMENTED { + t.Errorf("qre.Execute: %v, want %v", code, vtrpcpb.Code_INVALID_ARGUMENT) + } + + tsv.qe.allowUnsafeDMLs = true + got, err = qre.Execute() + if err != nil { + t.Fatalf("qre.Execute() = %v, want nil", err) + } + if !reflect.DeepEqual(got, want) { + t.Fatalf("got: %v, want: %v", got, want) + } +} + func TestQueryExecutorPlanPassDmlReplaceInto(t *testing.T) { db := setUpQueryExecutorTest(t) defer db.Close() diff --git a/go/vt/vttablet/tabletserver/tabletenv/config.go b/go/vt/vttablet/tabletserver/tabletenv/config.go index 2baf3f81637..66370d87651 100644 --- a/go/vt/vttablet/tabletserver/tabletenv/config.go +++ b/go/vt/vttablet/tabletserver/tabletenv/config.go @@ -55,7 +55,9 @@ func init() { flag.Float64Var(&Config.TxShutDownGracePeriod, "transaction_shutdown_grace_period", DefaultQsConfig.TxShutDownGracePeriod, "how long to wait (in seconds) for transactions to complete during graceful shutdown.") flag.IntVar(&Config.MaxResultSize, "queryserver-config-max-result-size", DefaultQsConfig.MaxResultSize, "query server max result size, maximum number of rows allowed to return from vttablet for non-streaming queries.") flag.IntVar(&Config.WarnResultSize, "queryserver-config-warn-result-size", DefaultQsConfig.WarnResultSize, "query server result size warning threshold, warn if number of rows returned from vttablet for non-streaming queries exceeds this") - flag.IntVar(&Config.MaxDMLRows, "queryserver-config-max-dml-rows", DefaultQsConfig.MaxDMLRows, "query server max dml rows per statement, maximum number of rows allowed to return at a time for an upadte or delete with either 1) an equality where clauses on primary keys, or 2) a subselect statement. For update and delete statements in above two categories, vttablet will split the original query into multiple small queries based on this configuration value. ") + flag.IntVar(&Config.MaxDMLRows, "queryserver-config-max-dml-rows", DefaultQsConfig.MaxDMLRows, "query server max dml rows per statement, maximum number of rows allowed to return at a time for an update or delete with either 1) an equality where clauses on primary keys, or 2) a subselect statement. For update and delete statements in above two categories, vttablet will split the original query into multiple small queries based on this configuration value. ") + flag.BoolVar(&Config.PassthroughDMLs, "queryserver-config-passthrough-dmls", DefaultQsConfig.PassthroughDMLs, "query server pass through all dml statements without rewriting") + flag.IntVar(&Config.StreamBufferSize, "queryserver-config-stream-buffer-size", DefaultQsConfig.StreamBufferSize, "query server stream buffer size, the maximum number of bytes sent from vttablet for each stream call. It's recommended to keep this value in sync with vtgate's stream_buffer_size.") flag.IntVar(&Config.QueryPlanCacheSize, "queryserver-config-query-cache-size", DefaultQsConfig.QueryPlanCacheSize, "query server query cache size, maximum number of queries to be cached. vttablet analyzes every incoming query and generate a query plan, these plans are being cached in a lru cache. This config controls the capacity of the lru cache.") flag.Float64Var(&Config.SchemaReloadTime, "queryserver-config-schema-reload-time", DefaultQsConfig.SchemaReloadTime, "query server schema reload time, how often vttablet reloads schemas from underlying MySQL instance in seconds. vttablet keeps table schemas in its own memory and periodically refreshes it from MySQL. This config controls the reload time.") @@ -128,6 +130,7 @@ type TabletConfig struct { MaxResultSize int WarnResultSize int MaxDMLRows int + PassthroughDMLs bool StreamBufferSize int QueryPlanCacheSize int SchemaReloadTime float64 @@ -194,6 +197,7 @@ var DefaultQsConfig = TabletConfig{ MaxResultSize: 10000, WarnResultSize: 0, MaxDMLRows: 500, + PassthroughDMLs: false, QueryPlanCacheSize: 5000, SchemaReloadTime: 30 * 60, QueryTimeout: 30, diff --git a/helm/vitess/Chart.yaml b/helm/vitess/Chart.yaml index 7a3cfc5004d..368ea4d0232 100644 --- a/helm/vitess/Chart.yaml +++ b/helm/vitess/Chart.yaml @@ -1,10 +1,13 @@ apiVersion: v1 name: vitess -version: 0.2.0 +version: 0.9.0 description: Single-Chart Vitess Cluster keywords: - vitess - mysql + - maria + - mariadb + - percona - sql - database - shard diff --git a/helm/vitess/README.md b/helm/vitess/README.md index 264d6b85dfa..018506672e2 100644 --- a/helm/vitess/README.md +++ b/helm/vitess/README.md @@ -14,12 +14,22 @@ It currently includes all dependencies (e.g. etcd) and Vitess components **WARNING: This chart should be considered Alpha. Upgrading a release of this chart may or may not delete all your data.** +## Prerequisites + +* Install [etcd-operator](https://github.com/coreos/etcd-operator) in the + namespace where you plan to install this chart. + ## Installing the Chart ```console -helm/vitess$ helm install . +helm/vitess$ helm install . -f site-values.yaml ``` +See the [Configuration](#configuration) section below for what you need to put +in `site-values.yaml`. +You can install the chart without site values, but it will only launch a +skeleton cluster without any keyspaces (logical databases). + ## Cleaning up After deleting an installation of the chart, the PersistentVolumeClaims remain. @@ -31,5 +41,179 @@ kubectl delete pvc -l app=vitess ## Configuration -See the comments in `values.yaml` for descriptions of the parameters. +You will need to provide a `site-values.yaml` file to specify your actual +logical database topology (e.g. whether to shard). +Here are examples of various configurations. To see additional options, +look at the default `values.yaml` file, which is well commented. + +### Unsharded keyspace + +``` +topology: + cells: + - name: "zone1" + etcd: + replicas: 3 + vtctld: + replicas: 1 + vtgate: + replicas: 3 + mysqlProtocol: + enabled: false + keyspaces: + - name: "unsharded-dbname" + shards: + - name: "0" + tablets: + - type: "replica" + vttablet: + replicas: 2 +``` + +### Unsharded + sharded keyspaces + +``` +topology: + cells: + - name: "zone1" + ... + keyspaces: + - name: "unsharded-dbname" + shards: + - name: "0" + tablets: + - type: "replica" + vttablet: + replicas: 2 + - name: "sharded-db" + shards: + - name: "-80" + tablets: + - type: "replica" + vttablet: + replicas: 2 + - name: "80-" + tablets: + - type: "replica" + vttablet: + replicas: 2 +``` + +### Separate pools of replicas and rdonly tablets + +``` +topology: + cells: + - name: "zone1" + ... + keyspaces: + - name: "unsharded-dbname" + shards: + - name: "0" + tablets: + - type: "replica" + vttablet: + replicas: 2 + - type: "rdonly" + vttablet: + replicas: 2 +``` + +### Use a custom database image and a specific Vitess release + +``` +topology: + cells: + ... + +vttablet: + vitessTag: "2.1" + mysqlImage: "percona:5.7.20" + flavor: percona +``` + +### Enable MySQL protocol support +``` +topology: + cells: + - name: "zone1" + ... + # enable or disable mysql protocol support, with accompanying auth details + mysqlProtocol: + enabled: false + username: myuser + # this is the secret that will be mounted as the user password + # kubectl create secret generic myuser_password --from-literal=password=abc123 + passwordSecret: myuser-password + + keyspaces: + ... +``` + +### Enable backup/restore using Google Cloud Storage + +``` +topology: + cells: + ... + +config: + backup: + enabled: true + backup_storage_implementation: gcs + + # Google Cloud Storage bucket to use for backups + gcs_backup_storage_bucket: vitess-backups + + # root prefix for all backup-related object names + gcs_backup_storage_root: vtbackups +``` + +### Custom requests/limits + +``` +topology: + cells: + ... + +vttablet: + resources: + # common production values 2-4CPU/4-8Gi RAM + limits: + cpu: 2 + memory: 4Gi + mysqlResources: + # common production values 4CPU/8-16Gi RAM + limits: + cpu: 4 + memory: 8Gi + # PVC for mysql + dataVolumeClaimAnnotations: + dataVolumeClaimSpec: + # pd-ssd (Google Cloud) + # managed-premium (Azure) + # standard (AWS) - not sure what the default class is for ssd + storageClassName: "default" + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: "10Gi" +``` + +### Custom PVC for MySQL data + +``` +topology: + cells: + ... + +vttablet: + dataVolumeClaimSpec: + # Google Cloud SSD + storageClassName: "pd-ssd" + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: "100Gi" +``` diff --git a/helm/vitess/orchestrator.conf.json b/helm/vitess/orchestrator.conf.json deleted file mode 100644 index bcdfeca631a..00000000000 --- a/helm/vitess/orchestrator.conf.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "Debug": true, - "EnableSyslog": false, - "ListenAddress": ":3000", - "AgentsServerPort": ":3001", - "MySQLTopologyUser": "orc_client_user", - "MySQLTopologyPassword": "orc_client_user_password", - "MySQLTopologyCredentialsConfigFile": "", - "MySQLTopologySSLPrivateKeyFile": "", - "MySQLTopologySSLCertFile": "", - "MySQLTopologySSLCAFile": "", - "MySQLTopologySSLSkipVerify": true, - "MySQLTopologyUseMutualTLS": false, - "MySQLTopologyMaxPoolConnections": 3, - "DatabaselessMode__experimental": false, - "MySQLOrchestratorHost": "127.0.0.1", - "MySQLOrchestratorPort": 3306, - "MySQLOrchestratorDatabase": "orchestrator", - "MySQLOrchestratorUser": "orc_server_user", - "MySQLOrchestratorPassword": "orc_server_user_password", - "MySQLOrchestratorCredentialsConfigFile": "", - "MySQLOrchestratorSSLPrivateKeyFile": "", - "MySQLOrchestratorSSLCertFile": "", - "MySQLOrchestratorSSLCAFile": "", - "MySQLOrchestratorSSLSkipVerify": true, - "MySQLOrchestratorUseMutualTLS": false, - "MySQLConnectTimeoutSeconds": 1, - "DefaultInstancePort": 3306, - "SkipOrchestratorDatabaseUpdate": false, - "SlaveLagQuery": "", - "SlaveStartPostWaitMilliseconds": 1000, - "DiscoverByShowSlaveHosts": true, - "InstancePollSeconds": 12, - "ReadLongRunningQueries": true, - "UnseenInstanceForgetHours": 240, - "SnapshotTopologiesIntervalHours": 0, - "DiscoveryPollSeconds": 5, - "InstanceBulkOperationsWaitTimeoutSeconds": 10, - "ActiveNodeExpireSeconds": 12, - "HostnameResolveMethod": "none", - "MySQLHostnameResolveMethod": "@@report_host", - "SkipBinlogServerUnresolveCheck": true, - "ExpiryHostnameResolvesMinutes": 0, - "RejectHostnameResolvePattern": "", - "ReasonableReplicationLagSeconds": 10, - "ProblemIgnoreHostnameFilters": [], - "VerifyReplicationFilters": false, - "MaintenanceOwner": "orchestrator", - "ReasonableMaintenanceReplicationLagSeconds": 20, - "MaintenanceExpireMinutes": 10, - "MaintenancePurgeDays": 365, - "CandidateInstanceExpireMinutes": 60, - "AuditLogFile": "/tmp/orchestrator-audit.log", - "AuditToSyslog": false, - "AuditPageSize": 20, - "AuditPurgeDays": 365, - "RemoveTextFromHostnameDisplay": ".mydomain.com:3306", - "ReadOnly": false, - "AuthenticationMethod": "", - "HTTPAuthUser": "", - "HTTPAuthPassword": "", - "AuthUserHeader": "", - "PowerAuthUsers": [ - "*" - ], - "ClusterNameToAlias": { - "127.0.0.1": "test suite" - }, - "DetectClusterAliasQuery": "SELECT value FROM _vt.local_metadata WHERE name='ClusterAlias'", - "DetectClusterDomainQuery": "", - "DetectInstanceAliasQuery": "SELECT value FROM _vt.local_metadata WHERE name='Alias'", - "DetectPromotionRuleQuery": "SELECT value FROM _vt.local_metadata WHERE name='PromotionRule'", - "DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com", - "PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com", - "PromotionIgnoreHostnameFilters": [], - "DetectSemiSyncEnforcedQuery": "SELECT @@global.rpl_semi_sync_master_wait_no_slave AND @@global.rpl_semi_sync_master_timeout > 1000000", - "ServeAgentsHttp": false, - "AgentsUseSSL": false, - "AgentsUseMutualTLS": false, - "AgentSSLSkipVerify": false, - "AgentSSLPrivateKeyFile": "", - "AgentSSLCertFile": "", - "AgentSSLCAFile": "", - "AgentSSLValidOUs": [], - "UseSSL": false, - "UseMutualTLS": false, - "SSLSkipVerify": false, - "SSLPrivateKeyFile": "", - "SSLCertFile": "", - "SSLCAFile": "", - "SSLValidOUs": [], - "StatusEndpoint": "/api/status", - "StatusSimpleHealth": true, - "StatusOUVerify": false, - "HttpTimeoutSeconds": 60, - "AgentPollMinutes": 60, - "AgentAutoDiscover": false, - "UnseenAgentForgetHours": 6, - "StaleSeedFailMinutes": 60, - "SeedAcceptableBytesDiff": 8192, - "PseudoGTIDPattern": "drop view if exists .*?`_pseudo_gtid_hint__", - "PseudoGTIDMonotonicHint": "asc:", - "DetectPseudoGTIDQuery": "", - "BinlogEventsChunkSize": 10000, - "BufferBinlogEvents": true, - "SkipBinlogEventsContaining": [], - "ReduceReplicationAnalysisCount": true, - "FailureDetectionPeriodBlockMinutes": 60, - "RecoveryPollSeconds": 10, - "RecoveryPeriodBlockMinutes": 1, - "RecoveryPeriodBlockSeconds": 60, - "RecoveryIgnoreHostnameFilters": [], - "RecoverMasterClusterFilters": [ - ".*" - ], - "RecoverIntermediateMasterClusterFilters": [ - "_intermediate_master_pattern_" - ], - "OnFailureDetectionProcesses": [ - "echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countSlaves}' >> /tmp/recovery.log" - ], - "PreFailoverProcesses": [ - "echo 'Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log" - ], - "PostFailoverProcesses": [ - "echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log" - ], - "PostUnsuccessfulFailoverProcesses": [], - "PostMasterFailoverProcesses": [ - "echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log", - "vtctlclient -server vtctld:15999 TabletExternallyReparented {successorAlias}" - ], - "PostIntermediateMasterFailoverProcesses": [ - "echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log" - ], - "CoMasterRecoveryMustPromoteOtherCoMaster": true, - "DetachLostSlavesAfterMasterFailover": true, - "ApplyMySQLPromotionAfterMasterFailover": true, - "MasterFailoverLostInstancesDowntimeMinutes": 0, - "PostponeSlaveRecoveryOnLagMinutes": 0, - "OSCIgnoreHostnameFilters": [], - "GraphiteAddr": "", - "GraphitePath": "", - "GraphiteConvertHostnameDotsToUnderscores": true -} diff --git a/helm/vitess/templates/NOTES.txt b/helm/vitess/templates/NOTES.txt index a08bd9830f4..a59ef214f5d 100644 --- a/helm/vitess/templates/NOTES.txt +++ b/helm/vitess/templates/NOTES.txt @@ -1,4 +1,4 @@ -{{- $cell := (index .Values.topology.cells 1).name -}} +{{- $cell := (index .Values.topology.cells 0).name -}} {{- $proxyURL := printf "http://localhost:8001/api/v1/proxy/namespaces/%s" .Release.Namespace -}} Release name: {{.Release.Name}} @@ -8,8 +8,6 @@ To access administrative web pages, start a proxy with: Then use the following URLs: -Kubernetes dashboard: http://localhost:8001/ui - -vtctld: {{$proxyURL}}/services/vtctld:web/ +vtctld: {{$proxyURL}}/services/vtctld:web/app/ vtgate: {{$proxyURL}}/services/vtgate-{{$cell}}:web/ diff --git a/helm/vitess/templates/_etcd.tpl b/helm/vitess/templates/_etcd.tpl index 9abefbf15eb..2145e9c41b9 100644 --- a/helm/vitess/templates/_etcd.tpl +++ b/helm/vitess/templates/_etcd.tpl @@ -1,149 +1,34 @@ +################################### +# etcd cluster managed by pre-installed etcd operator +################################### {{- define "etcd" -}} -{{- $ := index . 0 -}} -{{- $cell := index . 1 -}} -{{- with (index . 2) -}} -{{- $0 := $.Values.etcd -}} -{{- $replicas := .replicas | default $0.replicas -}} -# etcd -# Regular service for load balancing client connections. -kind: Service -apiVersion: v1 +# set tuple values to more recognizable variables +{{- $name := index . 0 -}} +{{- $replicas := index . 1 -}} +{{- $version := index . 2 -}} +{{- $resources := index . 3 -}} + +################################### +# EtcdCluster +################################### +apiVersion: "etcd.database.coreos.com/v1beta2" +kind: "EtcdCluster" metadata: - name: "etcd-{{$cell.name}}" - labels: - component: etcd - cell: {{$cell.name | quote}} - app: vitess + name: "etcd-{{ $name }}" spec: - ports: - - port: 4001 - selector: - component: etcd - cell: {{$cell.name | quote}} - app: vitess ---- -# Headless service for etcd cluster bootstrap. -kind: Service -apiVersion: v1 -metadata: - name: "etcd-{{$cell.name}}-srv" - labels: - component: etcd - cell: {{$cell.name | quote}} - app: vitess -spec: - clusterIP: None - ports: - - name: etcd-server - port: 7001 - selector: - component: etcd - cell: {{$cell.name | quote}} - app: vitess ---- -apiVersion: extensions/v1beta1 -kind: ReplicaSet -metadata: - name: "etcd-{{$cell.name}}" -spec: - replicas: {{$replicas}} - template: - metadata: - labels: - component: etcd - cell: {{$cell.name | quote}} - app: vitess - spec: - volumes: - - name: certs - hostPath: { path: {{$.Values.certsPath | quote}} } - containers: - - name: etcd - image: {{.image | default $0.image | quote}} - volumeMounts: - - name: certs - readOnly: true - # Mount root certs from the host OS into the location - # expected for our container OS (Debian): - mountPath: /etc/ssl/certs/ca-certificates.crt - resources: -{{ toYaml (.resources | default $0.resources) | indent 12 }} - command: - - bash - - "-c" - - | - set -ex - - ipaddr=$(hostname -i) - peer_url="http://$ipaddr:7001" - client_url="http://$ipaddr:4001" - - export ETCD_NAME=$HOSTNAME - export ETCD_DATA_DIR=/vt/vtdataroot/etcd-$ETCD_NAME - export ETCD_STRICT_RECONFIG_CHECK=true - export ETCD_ADVERTISE_CLIENT_URLS=$client_url - export ETCD_INITIAL_ADVERTISE_PEER_URLS=$peer_url - export ETCD_LISTEN_CLIENT_URLS=$client_url - export ETCD_LISTEN_PEER_URLS=$peer_url - - if [ -d $ETCD_DATA_DIR ]; then - # We've been restarted with an intact datadir. - # Just run without trying to do any bootstrapping. - echo "Resuming with existing data dir: $ETCD_DATA_DIR" - else - # This is the first run for this member. - - # If there's already a functioning cluster, join it. - echo "Checking for existing cluster by trying to join..." - if result=$(etcdctl -C http://etcd-{{$cell.name}}:4001 member add $ETCD_NAME $peer_url); then - [[ "$result" =~ ETCD_INITIAL_CLUSTER=\"([^\"]*)\" ]] && \ - export ETCD_INITIAL_CLUSTER="${BASH_REMATCH[1]}" - export ETCD_INITIAL_CLUSTER_STATE=existing - echo "Joining existing cluster: $ETCD_INITIAL_CLUSTER" - else - # Join failed. Assume we're trying to bootstrap. - - # First register with global topo, if we aren't global. - if [ "{{$cell.name}}" != "global" ]; then - echo "Registering cell "{{$cell.name}}" with global etcd..." - until etcdctl -C "http://etcd-global:4001" \ - set "/vt/cells/{{$cell.name}}" "http://etcd-{{$cell.name}}:4001"; do - echo "[$(date)] waiting for global etcd to register cell '{{$cell.name}}'" - sleep 1 - done - fi - - # Use DNS to bootstrap. - - # First wait for the desired number of replicas to show up. - echo "Waiting for {{$replicas}} replicas in SRV record for etcd-{{$cell.name}}-srv..." - until [ $(getsrv etcd-server tcp etcd-{{$cell.name}}-srv | wc -l) -eq {{$replicas}} ]; do - echo "[$(date)] waiting for {{$replicas}} entries in SRV record for etcd-{{$cell.name}}-srv" - sleep 1 - done - - export ETCD_DISCOVERY_SRV=etcd-{{$cell.name}}-srv - echo "Bootstrapping with DNS discovery:" - getsrv etcd-server tcp etcd-{{$cell.name}}-srv - fi - fi - - # We've set up the env as we want it. Now run. - exec etcd - lifecycle: - preStop: - exec: - command: - - bash - - "-c" - - | - # Find our member ID. - members=$(etcdctl -C http://etcd-{{$cell.name}}:4001 member list) - if [[ "$members" =~ ^([0-9a-f]+):\ name=$HOSTNAME ]]; then - member_id=${BASH_REMATCH[1]} - echo "Removing $HOSTNAME ($member_id) from etcd-{{$cell.name}} cluster..." - etcdctl -C http://etcd-{{$cell.name}}:4001 member remove $member_id - fi -{{- end -}} + size: {{ $replicas }} + version: {{ $version | quote }} + pod: + resources: +{{ toYaml ($resources) | indent 6 }} + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + # prefer to stay away from other same-cell etcd pods + - weight: 100 + podAffinityTerm: + topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + etcd_cluster: "etcd-{{ $name }}" {{- end -}} - diff --git a/helm/vitess/templates/_helpers.tpl b/helm/vitess/templates/_helpers.tpl index 49d7185a642..b6957755df7 100644 --- a/helm/vitess/templates/_helpers.tpl +++ b/helm/vitess/templates/_helpers.tpl @@ -1,22 +1,28 @@ # Helper templates +############################# # Format a flag map into a command line, # as expected by the golang 'flag' package. # Boolean flags must be given a value, such as "true" or "false". +############################# {{- define "format-flags" -}} {{- range $key, $value := . -}} -{{$key}}={{$value | quote}} {{end -}} {{- end -}} +############################# # Format a list of flag maps into a command line. +############################# {{- define "format-flags-all" -}} {{- range . }}{{template "format-flags" .}}{{end -}} {{- end -}} +############################# # Clean labels, making sure it starts and ends with [A-Za-z0-9]. # This is especially important for shard names, which can start or end with # '-' (like -80 or 80-), which would be an invalid kubernetes label. +############################# {{- define "clean-label" -}} {{- $replaced_label := . | replace "_" "-"}} {{- if hasPrefix "-" . -}} @@ -28,24 +34,228 @@ x{{$replaced_label}} {{- end -}} {{- end -}} -# Common init-container to set up vtdataroot volume. -{{- define "init-vtdataroot" -}} -{{- $image := . -}} -{ - "name": "init-vtdataroot", - "image": {{$image | quote}}, - "imagePullPolicy": "IfNotPresent", - "command": ["bash", "-c", " - set -ex; - mkdir -p $VTDATAROOT/tmp; - chown vitess:vitess $VTDATAROOT $VTDATAROOT/tmp; - "], - "volumeMounts": [ - { - "name": "vtdataroot", - "mountPath": "/vt/vtdataroot" - } - ] -} +############################# +# injects default vitess environment variables +############################# +{{- define "vitess-env" -}} +- name: VTROOT + value: "/vt" +- name: VTDATAROOT + value: "/vtdataroot" +- name: GOBIN + value: "/vt/bin" +- name: VT_MYSQL_ROOT + value: "/usr" +- name: PKG_CONFIG_PATH + value: "/vt/lib" {{- end -}} +############################# +# inject default pod security +############################# +{{- define "pod-security" -}} +securityContext: + runAsUser: 1000 + fsGroup: 2000 + runAsNonRoot: true +{{- end -}} + +############################# +# support region nodeAffinity if defined +############################# +{{- define "node-affinity" -}} +{{- $region := . -}} +{{ with $region }} +nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "failure-domain.beta.kubernetes.io/region" + operator: In + values: [{{ $region | quote }}] +{{- end -}} +{{- end -}} + +############################# +# mycnf exec +############################# +{{- define "mycnf-exec" -}} + +if [ "$VT_DB_FLAVOR" = "percona" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mysql56.cnf + +elif [ "$VT_DB_FLAVOR" = "mysql" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mysql56.cnf + +elif [ "$VT_DB_FLAVOR" = "maria" ]; then + FLAVOR_MYCNF=/vt/config/mycnf/master_mariadb.cnf + +fi + +export EXTRA_MY_CNF="$FLAVOR_MYCNF:/vtdataroot/tabletdata/report-host.cnf:/vt/config/mycnf/rbr.cnf" + +{{- end -}} + +############################# +# +# all backup helpers below +# +############################# + +############################# +# backup flags - expects config.backup +############################# +{{- define "backup-flags" -}} + +{{ if .enabled }} +-restore_from_backup +-backup_storage_implementation=$VT_BACKUP_SERVICE + +{{ if eq .backup_storage_implementation "gcs" }} +-gcs_backup_storage_bucket=$VT_GCS_BACKUP_STORAGE_BUCKET +-gcs_backup_storage_root=$VT_GCS_BACKUP_STORAGE_ROOT + +{{ else if eq .backup_storage_implementation "s3" }} +-s3_backup_aws_region=$VT_S3_BACKUP_AWS_REGION +-s3_backup_storage_bucket=$VT_S3_BACKUP_STORAGE_BUCKET +-s3_backup_storage_root=$VT_S3_BACKUP_STORAGE_ROOT +-s3_backup_server_side_encryption=$VT_S3_BACKUP_SERVER_SIDE_ENCRYPTION +{{ end }} + +{{ end }} + +{{- end -}} + +############################# +# backup env - expects config.backup +############################# +{{- define "backup-env" -}} + +{{ if .enabled }} + +- name: VT_BACKUP_SERVICE + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.backup_storage_implementation + +{{ if eq .backup_storage_implementation "gcs" }} + +- name: VT_GCS_BACKUP_STORAGE_BUCKET + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.gcs_backup_storage_bucket +- name: VT_GCS_BACKUP_STORAGE_ROOT + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.gcs_backup_storage_root + +{{ else if eq .backup_storage_implementation "s3" }} + +- name: VT_S3_BACKUP_AWS_REGION + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.s3_backup_aws_region +- name: VT_S3_BACKUP_STORAGE_BUCKET + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.s3_backup_storage_bucket +- name: VT_S3_BACKUP_STORAGE_ROOT + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.s3_backup_storage_root +- name: VT_S3_BACKUP_SERVER_SIDE_ENCRYPTION + valueFrom: + configMapKeyRef: + name: vitess-cm + key: backup.s3_backup_server_side_encryption + +{{ end }} + +{{ end }} + +{{- end -}} + +############################# +# backup volume - expects config.backup +############################# +{{- define "backup-volume" -}} + +{{ if .enabled }} + + {{ if eq .backup_storage_implementation "gcs" }} + + {{ if .gcsSecret }} +- name: backup-creds + secret: + secretName: {{ .gcsSecret }} + {{ end }} + + {{ else if eq .backup_storage_implementation "s3" }} + + {{ if .s3Secret }} +- name: backup-creds + secret: + secretName: {{ .s3Secret }} + {{ end }} + + {{ end }} + +{{ end }} + +{{- end -}} + +############################# +# backup volumeMount - expects config.backup +############################# +{{- define "backup-volumeMount" -}} + +{{ if .enabled }} + + {{ if eq .backup_storage_implementation "gcs" }} + + {{ if .gcsSecret }} +- name: backup-creds + mountPath: /etc/secrets/creds + {{ end }} + + {{ else if eq .backup_storage_implementation "s3" }} + + {{ if .s3Secret }} +- name: backup-creds + mountPath: /etc/secrets/creds + {{ end }} + + {{ end }} + +{{ end }} + +{{- end -}} + +############################# +# backup exec +############################# +{{- define "backup-exec" -}} + +{{ if .enabled }} + +credsPath=/etc/secrets/creds/$(ls /etc/secrets/creds/ | head -1) + +{{ if eq .backup_storage_implementation "gcs" }} +export GOOGLE_APPLICATION_CREDENTIALS=$credsPath +cat $GOOGLE_APPLICATION_CREDENTIALS + +{{ else if eq .backup_storage_implementation "s3" }} +export AWS_SHARED_CREDENTIALS_FILE=$credsPath +cat $AWS_SHARED_CREDENTIALS_FILE + +{{ end }} + +{{ end }} + +{{- end -}} \ No newline at end of file diff --git a/helm/vitess/templates/_orchestrator.tpl b/helm/vitess/templates/_orchestrator.tpl deleted file mode 100644 index 64dd14054f4..00000000000 --- a/helm/vitess/templates/_orchestrator.tpl +++ /dev/null @@ -1,128 +0,0 @@ -{{- define "orchestrator" -}} -{{- $ := index . 0 -}} -{{- $cell := index . 1 -}} -{{- with index . 2 -}} -{{- $0 := $.Values.orchestrator -}} -{{- $dataVolumeType := .dataVolumeType | default $0.dataVolumeType -}} -# Orchestrator service -apiVersion: v1 -kind: Service -metadata: - name: orchestrator - labels: - component: orchestrator - app: vitess -spec: - ports: - - port: 80 - targetPort: 3000 - selector: - component: orchestrator - app: vitess -{{ if eq $dataVolumeType "PersistentVolume" }} ---- -# Orchestrator persistent volume claim -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: orchestrator-data - annotations: -{{ toYaml (.dataVolumeClaimAnnotations | default $0.dataVolumeClaimAnnotations) | indent 4 }} -spec: -{{ toYaml (.dataVolumeClaimSpec | default $0.dataVolumeClaimSpec) | indent 2 }} -{{ end }} ---- -# Orchestrator replication controller -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: orchestrator -spec: - replicas: {{.replicas | default $0.replicas}} - template: - metadata: - labels: - component: orchestrator - app: vitess - annotations: - pod.beta.kubernetes.io/init-containers: '[ - { - "name": "init-mysql", - "image": {{.image | default $0.image | quote}}, - "imagePullPolicy": "IfNotPresent", - "command": ["bash", "-c", " - set -ex\n - rm -rf /mnt/data/lost+found\n - if [[ ! -d /mnt/data/mysql ]]; then\n - cp -R /var/lib/mysql/* /mnt/data/\n - fi\n - chown -R mysql:mysql /mnt/data\n - "], - "volumeMounts": [ - {"name": "data", "mountPath": "/mnt/data"} - ] - } - ]' - spec: - containers: - - name: orchestrator - image: {{.image | default $0.image | quote}} - command: - - bash - - "-c" - - | - set -x - until mysqladmin -h 127.0.0.1 ping; do sleep 1; done - exec orchestrator http - livenessProbe: - httpGet: - path: "/" - port: 3000 - initialDelaySeconds: 300 - timeoutSeconds: 30 - readinessProbe: - httpGet: - path: "/" - port: 3000 - timeoutSeconds: 10 - volumeMounts: - - mountPath: /orc/conf - name: config - resources: -{{ toYaml (.resources | default $0.resources) | indent 12 }} - - name: mysql - image: {{.image | default $0.image | quote}} - volumeMounts: - - mountPath: /var/lib/mysql - name: data - livenessProbe: - exec: - command: ["mysqladmin", "ping"] - initialDelaySeconds: 60 - timeoutSeconds: 10 - resources: -{{ toYaml (.mysqlResources | default $0.mysqlResources) | indent 12 }} - command: ["mysqld"] - volumes: - - name: config - configMap: - name: orchestrator - - name: data -{{ if eq $dataVolumeType "PersistentVolume" }} - persistentVolumeClaim: - claimName: orchestrator-data -{{ else }} - emptyDir: {} -{{ end }} ---- -# Orchestrator ConfigMap -apiVersion: v1 -kind: ConfigMap -metadata: - name: orchestrator -data: - orchestrator.conf.json: | -{{ $.Files.Get "orchestrator.conf.json" | indent 4 }} -{{- end -}} -{{- end -}} - diff --git a/helm/vitess/templates/_vtctld.tpl b/helm/vitess/templates/_vtctld.tpl index 96584ede1d8..05dc0eb09e7 100644 --- a/helm/vitess/templates/_vtctld.tpl +++ b/helm/vitess/templates/_vtctld.tpl @@ -1,9 +1,23 @@ +################################### +# vtctld Service + Deployment +################################### {{- define "vtctld" -}} -{{- $ := index . 0 -}} +# set tuple values to more recognizable variables +{{- $topology := index . 0 -}} {{- $cell := index . 1 -}} -{{- with index . 2 -}} -{{- $0 := $.Values.vtctld -}} -# vtctld +{{- $defaultVtctld := index . 2 -}} +{{- $namespace := index . 3 -}} +{{- $config := index . 4 -}} + +{{- with $cell.vtctld -}} + +# define image to use +{{- $vitessTag := .vitessTag | default $defaultVtctld.vitessTag -}} +{{- $cellClean := include "clean-label" $cell.name -}} + +################################### +# vtctld Service +################################### kind: Service apiVersion: v1 metadata: @@ -20,112 +34,89 @@ spec: selector: component: vtctld app: vitess - type: {{.serviceType | default $0.serviceType}} + type: {{.serviceType | default $defaultVtctld.serviceType}} --- -apiVersion: extensions/v1beta1 +################################### +# vtctld Service + Deployment +################################### +apiVersion: apps/v1beta1 kind: Deployment metadata: name: vtctld spec: - replicas: {{.replicas | default $0.replicas}} + replicas: {{.replicas | default $defaultVtctld.replicas}} + selector: + matchLabels: + app: vitess + component: vtctld template: metadata: labels: - component: vtctld app: vitess - annotations: - pod.beta.kubernetes.io/init-containers: '[ -{{ include "init-vtdataroot" (.image | default $0.image) | indent 10 }}, - { - "name": "init-vtctld", - "image": {{.image | default $0.image | quote}}, - "imagePullPolicy": "IfNotPresent", - "command": ["bash", "-c", " - set -ex\n - rm -rf /vt/web/*\n - cp -R $VTTOP/web/* /vt/web/\n - cp /mnt/config/config.js /vt/web/vtctld/\n - "], - "volumeMounts": [ - { - "name": "config", - "mountPath": "/mnt/config" - }, - { - "name": "web", - "mountPath": "/vt/web" - } - ] - } - ]' + component: vtctld spec: +{{ include "pod-security" . | indent 6 }} +{{ include "vtctld-affinity" (tuple $cellClean $cell.region) | indent 6 }} containers: - name: vtctld - image: {{.image | default $0.image | quote}} + image: vitess/k8s:{{$vitessTag}} livenessProbe: httpGet: path: /debug/vars port: 15000 initialDelaySeconds: 30 timeoutSeconds: 5 + env: +{{ include "backup-env" $config.backup | indent 12 }} volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - - name: web - mountPath: /vt/web - - name: certs - readOnly: true - # Mount root certs from the host OS into the location - # expected for our container OS (Debian): - mountPath: /etc/ssl/certs/ca-certificates.crt +{{ include "backup-volumeMount" $config.backup | indent 12 }} + resources: -{{ toYaml (.resources | default $0.resources) | indent 12 }} - securityContext: - runAsUser: 999 +{{ toYaml (.resources | default $defaultVtctld.resources) | indent 12 }} command: - bash - "-c" - | - set -ex + set -ex; + +{{ include "backup-exec" $config.backup | indent 14 }} + eval exec /vt/bin/vtctld $(cat < /mysqlcreds/creds.json + +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/helm/vitess/templates/_vttablet.tpl b/helm/vitess/templates/_vttablet.tpl index 620ca956e8e..11127576d11 100644 --- a/helm/vitess/templates/_vttablet.tpl +++ b/helm/vitess/templates/_vttablet.tpl @@ -1,251 +1,425 @@ -# vttablet pod spec (template for both StatefulSet and naked pod) -{{- define "vttablet-pod-spec" -}} -{{- $ := index . 0 -}} -{{- $cell := index . 1 -}} -{{- $keyspace := index . 2 -}} -{{- $shard := index . 3 -}} -{{- $tablet := index . 4 -}} -{{- $uid := index . 5 -}} -{{- with index . 6 -}} -{{- $0 := $.Values.vttablet -}} -{{- $controllerType := .controllerType | default $0.controllerType -}} -containers: - - name: vttablet - image: {{.image | default $0.image | quote}} - livenessProbe: - httpGet: - path: /debug/vars - port: 15002 - initialDelaySeconds: 60 - timeoutSeconds: 10 - volumeMounts: - - name: syslog - mountPath: /dev/log - - name: vtdataroot - mountPath: /vt/vtdataroot - - name: certs - readOnly: true - # Mount root certs from the host OS into the location - # expected for our container OS (Debian): - mountPath: /etc/ssl/certs/ca-certificates.crt - resources: -{{ toYaml (.resources | default $0.resources) | indent 6 }} - ports: - - name: web - containerPort: 15002 - - name: grpc - containerPort: 16002 - securityContext: - runAsUser: 999 - command: - - bash - - "-c" - - | - set -ex - eval exec /vt/bin/vttablet $(cat < $VTDATAROOT/init/tablet-uid\n - # Tell MySQL what hostname to report in SHOW SLAVE HOSTS.\n - # Orchestrator looks there, so it should match -tablet_hostname above.\n - echo report-host=$hostname.vttablet > $VTDATAROOT/init/report-host.cnf\n - "], - "volumeMounts": [ - { - "name": "vtdataroot", - "mountPath": "/vt/vtdataroot" - } - ] -} {{- end -}} -# vttablet StatefulSet -{{- define "vttablet-stateful-set" -}} -{{- $ := index . 0 -}} +################################### +# vttablet +################################### +{{- define "vttablet" -}} +# set tuple values to more recognizable variables +{{- $topology := index . 0 -}} {{- $cell := index . 1 -}} {{- $keyspace := index . 2 -}} {{- $shard := index . 3 -}} {{- $tablet := index . 4 -}} -{{- with $tablet.vttablet -}} -{{- $0 := $.Values.vttablet -}} +{{- $defaultVttablet := index . 5 -}} +{{- $namespace := index . 6 -}} +{{- $config := index . 7 -}} + +# sanitize inputs to create tablet name {{- $cellClean := include "clean-label" $cell.name -}} {{- $keyspaceClean := include "clean-label" $keyspace.name -}} {{- $shardClean := include "clean-label" $shard.name -}} +{{- $uid := "$(cat /vtdataroot/tabletdata/tablet-uid)" }} {{- $setName := printf "%s-%s-%s-%s" $cellClean $keyspaceClean $shardClean $tablet.type | lower -}} -{{- $uid := "$(cat $VTDATAROOT/init/tablet-uid)" }} + +{{- with $tablet.vttablet -}} + +# define images to use +{{- $vitessTag := .vitessTag | default $defaultVttablet.vitessTag -}} +{{- $image := .image | default $defaultVttablet.image -}} +{{- $mysqlImage := .mysqlImage | default $defaultVttablet.mysqlImage -}} + +################################### # vttablet StatefulSet +################################### apiVersion: apps/v1beta1 kind: StatefulSet metadata: - name: {{$setName | quote}} + name: {{ $setName | quote }} spec: serviceName: vttablet - replicas: {{.replicas | default $0.replicas}} + replicas: {{ .replicas | default $defaultVttablet.replicas }} + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + app: vitess + component: vttablet + cell: {{ $cellClean | quote }} + keyspace: {{ $keyspaceClean | quote }} + shard: {{ $shardClean | quote }} + type: {{ $tablet.type | quote }} template: metadata: labels: app: vitess component: vttablet - cell: {{$cellClean | quote}} - keyspace: {{$keyspace.name | quote}} - shard: {{$shardClean | quote}} - type: {{$tablet.type | quote}} - annotations: - pod.alpha.kubernetes.io/initialized: "true" - pod.beta.kubernetes.io/init-containers: '[ -{{ include "init-vtdataroot" (.image | default $0.image) | indent 10 }}, -{{ include "init-tablet-uid" (tuple (.image | default $0.image) $cell) | indent 10 }} - ]' + cell: {{ $cellClean | quote }} + keyspace: {{ $keyspaceClean | quote }} + shard: {{ $shardClean | quote }} + type: {{ $tablet.type | quote }} spec: -{{ include "vttablet-pod-spec" (tuple $ $cell $keyspace $shard $tablet $uid .) | indent 6 }} -{{ if eq (.dataVolumeType | default $0.dataVolumeType) "PersistentVolume" }} +{{ include "pod-security" . | indent 6 }} +{{ include "vttablet-affinity" (tuple $cellClean $keyspaceClean $shardClean $cell.region) | indent 6 }} + + initContainers: +{{ include "init-mysql" (tuple $vitessTag $cellClean $namespace) | indent 8 }} +{{ include "init-tablet-uid" (tuple $vitessTag $cell) | indent 8 }} + + containers: +{{ include "cont-mysql" (tuple $topology $cell $keyspace $shard $tablet $defaultVttablet $uid) | indent 8 }} +{{ include "cont-vttablet" (tuple $topology $cell $keyspace $shard $tablet $defaultVttablet $vitessTag $uid $namespace $config) | indent 8 }} +{{ include "cont-mysql-errorlog" . | indent 8 }} +{{ include "cont-mysql-slowlog" . | indent 8 }} + + volumes: + - name: vt + emptyDir: {} +{{ include "backup-volume" $config.backup | indent 8 }} + volumeClaimTemplates: - metadata: name: vtdataroot annotations: -{{ toYaml (.dataVolumeClaimAnnotations | default $0.dataVolumeClaimAnnotations) | indent 10 }} +{{ toYaml (.dataVolumeClaimAnnotations | default $defaultVttablet.dataVolumeClaimAnnotations) | indent 10 }} spec: -{{ toYaml (.dataVolumeClaimSpec | default $0.dataVolumeClaimSpec) | indent 8 }} -{{ end }} +{{ toYaml (.dataVolumeClaimSpec | default $defaultVttablet.dataVolumeClaimSpec) | indent 8 }} + +{{- end -}} +{{- end -}} + +################################### +# init-container to copy binaries for mysql +################################### +{{- define "init-mysql" -}} +{{- $vitessTag := index . 0 -}} +{{- $cellClean := index . 1 -}} +{{- $namespace := index . 2 -}} + +- name: "init-mysql" + image: "vitess/k8s:{{$vitessTag}}" + imagePullPolicy: IfNotPresent + volumeMounts: + - name: vtdataroot + mountPath: "/vtdataroot" + - name: vt + mountPath: "/vttmp" + + command: ["bash"] + args: + - "-c" + - | + set -ex + # set up the directories vitess needs + mkdir -p /vttmp/bin + mkdir -p /vtdataroot/tabletdata + + # copy necessary assets to the volumeMounts + cp /vt/bin/mysqlctld /vttmp/bin/ + cp -R /vt/config /vttmp/ + + # make sure that etcd is initialized + eval exec /vt/bin/vtctl $(cat < /vtdataroot/tabletdata/tablet-uid + # Tell MySQL what hostname to report in SHOW SLAVE HOSTS. + echo report-host=$hostname.vttablet > /vtdataroot/tabletdata/report-host.cnf + # Orchestrator looks there, so it should match -tablet_hostname above. + +{{- end -}} + +########################## +# main vttablet container +########################## +{{- define "cont-vttablet" -}} + +{{- $topology := index . 0 -}} +{{- $cell := index . 1 -}} +{{- $keyspace := index . 2 -}} +{{- $shard := index . 3 -}} +{{- $tablet := index . 4 -}} +{{- $defaultVttablet := index . 5 -}} +{{- $vitessTag := index . 6 -}} +{{- $uid := index . 7 -}} +{{- $namespace := index . 8 -}} +{{- $config := index . 9 -}} + +{{- $cellClean := include "clean-label" $cell.name -}} +{{- with $tablet.vttablet -}} + +- name: vttablet + image: "vitess/k8s:{{$vitessTag}}" + livenessProbe: + httpGet: + path: /debug/vars + port: 15002 + initialDelaySeconds: 60 + timeoutSeconds: 10 + volumeMounts: + - name: vtdataroot + mountPath: "/vtdataroot" +{{ include "backup-volumeMount" $config.backup | indent 4 }} + + resources: +{{ toYaml (.resources | default $defaultVttablet.resources) | indent 6 }} + ports: + - name: web + containerPort: 15002 + - name: grpc + containerPort: 16002 + env: +{{ include "vitess-env" . | indent 4 }} +{{ include "backup-env" $config.backup | indent 4 }} + + - name: VT_DB_FLAVOR + valueFrom: + configMapKeyRef: + name: vitess-cm + key: db.flavor + + command: ["bash"] + args: + - "-c" + - | + set -ex + +{{ include "mycnf-exec" . | indent 6 }} +{{ include "backup-exec" $config.backup | indent 6 }} + + eval exec /vt/bin/vttablet $(cat <