From 1aae1b6499a06a24d959d5f15fb2b059e7ff257e Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 15 Mar 2021 13:33:36 +0100 Subject: [PATCH 01/49] fix regression - should be able to plan subquery on top of subquery Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/filtering.go | 2 + .../planbuilder/testdata/filter_cases.txt | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index 6193f66b5ec..4e22a3cdbc6 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -63,6 +63,8 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, } node.UpdatePlan(pb, filter) return node, nil + case *pulloutSubquery: + return planFilter(pb, node.underlying, filter, whereType, origin) case *vindexFunc: return filterVindexFunc(node, filter) case *subquery: diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index 48682ad7d6d..038e498bc60 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1773,3 +1773,46 @@ "SysTableTableSchema": "VARBINARY(\"ks\")" } } + +# pullout sq after pullout sq +"select id from user where not id in (select user_extra.col from user_extra where user_extra.user_id = 42) and id in (select user_extra.col from user_extra where user_extra.user_id = 411)" +{ + "QueryType": "SELECT", + "Original": "select id from user where not id in (select user_extra.col from user_extra where user_extra.user_id = 42) and id in (select user_extra.col from user_extra where user_extra.user_id = 411)", + "Instructions": { + "OperatorType": "Subquery", + "Variant": "PulloutIn", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col from user_extra where 1 != 1", + "Query": "select user_extra.col from user_extra where user_extra.user_id = 42", + "Table": "user_extra", + "Values": [ + 42 + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "SelectIN", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where :__sq_has_values1 = 1 and id in ::__vals and not (:__sq_has_values2 = 1 and id in ::__sq2)", + "Table": "user", + "Values": [ + "::__sq1" + ], + "Vindex": "user_index" + } + ] + } +} From 5643642fd3c5f3e858171d495605d0886f140356 Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Tue, 16 Mar 2021 11:38:43 +0200 Subject: [PATCH 02/49] ubuntu-18.04 Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- .github/workflows/unit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index ba58c5af400..e40b4921ab1 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 strategy: matrix: name: [percona56, mysql57, mysql80, mariadb101, mariadb102, mariadb103] From 2115fa64c42e405931c44b4a7c09cb1d39789c5c Mon Sep 17 00:00:00 2001 From: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> Date: Tue, 16 Mar 2021 11:49:16 +0200 Subject: [PATCH 03/49] all ubuntu-latest => ubuntu-18.04 Signed-off-by: Shlomi Noach <2607934+shlomi-noach@users.noreply.github.com> --- .github/workflows/check_formatting.yml | 2 +- .github/workflows/check_make_parser.yml | 2 +- .github/workflows/check_make_visitor.yml | 2 +- .github/workflows/cluster_endtoend.yml | 2 +- .github/workflows/cluster_endtoend_upgrade.yml | 2 +- .github/workflows/cluster_initial_sharding_multi.yml | 2 +- .github/workflows/create_release.yml | 2 +- .github/workflows/docker_test_1.yml | 4 ++-- .github/workflows/docker_test_2.yml | 4 ++-- .github/workflows/docker_test_3.yml | 2 +- .github/workflows/e2e_race.yml | 2 +- .github/workflows/endtoend.yml | 2 +- .github/workflows/ensure_bootstrap_updated.yml | 2 +- .github/workflows/golangci-linter.yml | 2 +- .github/workflows/sonar_analysis.yml | 2 +- .github/workflows/unit_race.yml | 2 +- 16 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/check_formatting.yml b/.github/workflows/check_formatting.yml index 3f2334dd4bb..9c64b18ced4 100644 --- a/.github/workflows/check_formatting.yml +++ b/.github/workflows/check_formatting.yml @@ -4,7 +4,7 @@ jobs: build: name: Check Formatting - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/check_make_parser.yml b/.github/workflows/check_make_parser.yml index 805cf2fe494..c856da3e580 100644 --- a/.github/workflows/check_make_parser.yml +++ b/.github/workflows/check_make_parser.yml @@ -4,7 +4,7 @@ jobs: build: name: Check Make Parser - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/check_make_visitor.yml b/.github/workflows/check_make_visitor.yml index 219e1ece2dc..b72fbbaf514 100644 --- a/.github/workflows/check_make_visitor.yml +++ b/.github/workflows/check_make_visitor.yml @@ -4,7 +4,7 @@ jobs: build: name: Check Make Visitor - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/cluster_endtoend.yml b/.github/workflows/cluster_endtoend.yml index 60edd6e3405..4ec4671d62f 100644 --- a/.github/workflows/cluster_endtoend.yml +++ b/.github/workflows/cluster_endtoend.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 strategy: matrix: name: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27] diff --git a/.github/workflows/cluster_endtoend_upgrade.yml b/.github/workflows/cluster_endtoend_upgrade.yml index 185b9fbbe09..e7ad8653838 100644 --- a/.github/workflows/cluster_endtoend_upgrade.yml +++ b/.github/workflows/cluster_endtoend_upgrade.yml @@ -4,7 +4,7 @@ jobs: build: name: Run endtoend tests on Cluster (upgrade) - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/cluster_initial_sharding_multi.yml b/.github/workflows/cluster_initial_sharding_multi.yml index 147b8e7e1cf..494dfca2bb6 100644 --- a/.github/workflows/cluster_initial_sharding_multi.yml +++ b/.github/workflows/cluster_initial_sharding_multi.yml @@ -4,7 +4,7 @@ jobs: build: name: cluster initial sharding multi - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index 85a4d098d5c..f126dd76e35 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -10,7 +10,7 @@ on: jobs: build: name: Create Release - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/docker_test_1.yml b/.github/workflows/docker_test_1.yml index f15e3a3f9bd..11a53e1a48b 100644 --- a/.github/workflows/docker_test_1.yml +++ b/.github/workflows/docker_test_1.yml @@ -4,7 +4,7 @@ jobs: build: name: Docker Test 1 - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: @@ -18,4 +18,4 @@ jobs: - name: Run tests which require docker - 1 run: | - go run test.go -docker=true --follow -shard 10 \ No newline at end of file + go run test.go -docker=true --follow -shard 10 diff --git a/.github/workflows/docker_test_2.yml b/.github/workflows/docker_test_2.yml index 84ea569d5de..46d04889bbd 100644 --- a/.github/workflows/docker_test_2.yml +++ b/.github/workflows/docker_test_2.yml @@ -4,7 +4,7 @@ jobs: build: name: Docker Test 2 - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: @@ -18,4 +18,4 @@ jobs: - name: Run tests which require docker - 2 run: | - go run test.go -docker=true --follow -shard 25 \ No newline at end of file + go run test.go -docker=true --follow -shard 25 diff --git a/.github/workflows/docker_test_3.yml b/.github/workflows/docker_test_3.yml index 92c9e0cbe5f..6cc880e992f 100644 --- a/.github/workflows/docker_test_3.yml +++ b/.github/workflows/docker_test_3.yml @@ -4,7 +4,7 @@ jobs: build: name: Docker Test 3 - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: diff --git a/.github/workflows/e2e_race.yml b/.github/workflows/e2e_race.yml index b6ce4793970..1b66cdcbe13 100644 --- a/.github/workflows/e2e_race.yml +++ b/.github/workflows/e2e_race.yml @@ -4,7 +4,7 @@ jobs: build: name: End-to-End Test (Race) - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/endtoend.yml b/.github/workflows/endtoend.yml index 026e8f1f4ef..8be2dbb3179 100644 --- a/.github/workflows/endtoend.yml +++ b/.github/workflows/endtoend.yml @@ -4,7 +4,7 @@ jobs: build: name: End-to-End Test - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/ensure_bootstrap_updated.yml b/.github/workflows/ensure_bootstrap_updated.yml index 3ec8261c9b6..6bb1af2eb76 100644 --- a/.github/workflows/ensure_bootstrap_updated.yml +++ b/.github/workflows/ensure_bootstrap_updated.yml @@ -4,7 +4,7 @@ jobs: build: name: Check Bootstrap Updated - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/golangci-linter.yml b/.github/workflows/golangci-linter.yml index b91b8d06a47..bc6799331ff 100644 --- a/.github/workflows/golangci-linter.yml +++ b/.github/workflows/golangci-linter.yml @@ -3,7 +3,7 @@ on: [push, pull_request] jobs: build: name: Build - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go 1.15 uses: actions/setup-go@v1 diff --git a/.github/workflows/sonar_analysis.yml b/.github/workflows/sonar_analysis.yml index 3381d93b223..af59daa03b7 100644 --- a/.github/workflows/sonar_analysis.yml +++ b/.github/workflows/sonar_analysis.yml @@ -6,7 +6,7 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go diff --git a/.github/workflows/unit_race.yml b/.github/workflows/unit_race.yml index 7e71449de83..d280afe62a6 100644 --- a/.github/workflows/unit_race.yml +++ b/.github/workflows/unit_race.yml @@ -4,7 +4,7 @@ jobs: build: name: Unit Test (Race) - runs-on: ubuntu-latest + runs-on: ubuntu-18.04 steps: - name: Set up Go From b6e31d24b5b66c4013973b3e674dc8fd17d756c5 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 9 Mar 2021 16:12:15 +0530 Subject: [PATCH 04/49] added e2e test for unsharded reserved connection transaction Signed-off-by: Harshit Gangal --- .../endtoend/vtgate/unsharded/main_test.go | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index f5c3ebce188..2dd99bca9b9 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" @@ -215,6 +216,29 @@ func TestDDLUnsharded(t *testing.T) { assertMatches(t, conn, "show tables", `[[VARCHAR("allDefaults")] [VARCHAR("t1")]]`) } +func TestReservedConnDML(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + exec(t, conn, `set default_week_format = 1`) + exec(t, conn, `begin`) + exec(t, conn, `insert into allDefaults () values ()`) + exec(t, conn, `commit`) + + time.Sleep(35 * time.Second) + + exec(t, conn, `begin`) + exec(t, conn, `insert into allDefaults () values ()`) + exec(t, conn, `commit`) +} + func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { t.Helper() qr, err := conn.ExecuteFetch(query, 1000, true) From 7db4e526f62f009d5a777bc877944d57e3bd4ba4 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 9 Mar 2021 18:43:06 +0530 Subject: [PATCH 05/49] added unit test for reserved conn issue Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_dml_test.go | 53 +++++++++++++++++++++++ go/vt/vttablet/sandboxconn/sandboxconn.go | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/go/vt/vtgate/executor_dml_test.go b/go/vt/vtgate/executor_dml_test.go index 0902738fefc..11bee5a489c 100644 --- a/go/vt/vtgate/executor_dml_test.go +++ b/go/vt/vtgate/executor_dml_test.go @@ -23,6 +23,8 @@ import ( "github.com/stretchr/testify/assert" + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/utils" "github.com/stretchr/testify/require" @@ -1737,3 +1739,54 @@ func TestDeleteLookupOwnedEqual(t *testing.T) { utils.MustMatch(t, sbc1.Queries, sbc1wantQueries, "") utils.MustMatch(t, sbc2.Queries, sbc2wantQueries, "") } + +func TestReservedConnDML(t *testing.T) { + executor, _, _, sbc := createExecutorEnv() + + logChan := QueryLogger.Subscribe("TestReservedConnDML") + defer QueryLogger.Unsubscribe(logChan) + + ctx := context.Background() + session := NewAutocommitSession(&vtgatepb.Session{EnableSystemSettings: true}) + + _, err := executor.Execute(ctx, "TestReservedConnDML", session, "use "+KsTestUnsharded, nil) + require.NoError(t, err) + + wantQueries := []*querypb.BoundQuery{ + {Sql: "select 1 from dual where @@default_week_format != 1", BindVariables: map[string]*querypb.BindVariable{}}, + } + sbc.SetResults([]*sqltypes.Result{ + sqltypes.MakeTestResult(sqltypes.MakeTestFields("id", "int64"), "1"), + }) + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "set default_week_format = 1", nil) + require.NoError(t, err) + utils.MustMatch(t, wantQueries, sbc.Queries) + + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "begin", nil) + require.NoError(t, err) + + wantQueries = append(wantQueries, + &querypb.BoundQuery{Sql: "set @@default_week_format = 1", BindVariables: map[string]*querypb.BindVariable{}}, + &querypb.BoundQuery{Sql: "insert into simple values ()", BindVariables: map[string]*querypb.BindVariable{}}) + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "insert into simple() values ()", nil) + require.NoError(t, err) + utils.MustMatch(t, wantQueries, sbc.Queries) + + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "commit", nil) + require.NoError(t, err) + + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "begin", nil) + require.NoError(t, err) + + sbc.EphemeralShardErr = mysql.NewSQLError(mysql.CRServerGone, mysql.SSNetError, "connection gone") + // as the first time the query fails due to connection loss i.e. reserved conn lost. It will be recreated to set statement will be executed again. + wantQueries = append(wantQueries, + &querypb.BoundQuery{Sql: "set @@default_week_format = 1", BindVariables: map[string]*querypb.BindVariable{}}, + &querypb.BoundQuery{Sql: "insert into simple values ()", BindVariables: map[string]*querypb.BindVariable{}}) + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "insert into simple() values ()", nil) + require.NoError(t, err) + utils.MustMatch(t, wantQueries, sbc.Queries) + + _, err = executor.Execute(ctx, "TestReservedConnDML", session, "commit", nil) + require.NoError(t, err) +} diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 3a9816118b1..823cb312de1 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -441,7 +441,7 @@ func (sbc *SandboxConn) HandlePanic(err *error) { //ReserveBeginExecute implements the QueryService interface func (sbc *SandboxConn) ReserveBeginExecute(ctx context.Context, target *querypb.Target, preQueries []string, sql string, bindVariables map[string]*querypb.BindVariable, options *querypb.ExecuteOptions) (*sqltypes.Result, int64, int64, *topodatapb.TabletAlias, error) { reservedID := sbc.reserve(ctx, target, preQueries, bindVariables, 0, options) - result, transactionID, alias, err := sbc.BeginExecute(ctx, target, preQueries, sql, bindVariables, reservedID, options) + result, transactionID, alias, err := sbc.BeginExecute(ctx, target, nil, sql, bindVariables, reservedID, options) if transactionID != 0 { sbc.txIDToRID[transactionID] = reservedID } From b6056dab7c06bea1bbc0b11e44024db4a06776dd Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 9 Mar 2021 19:01:57 +0530 Subject: [PATCH 06/49] Two changes here: 1. Update the shard sessions only if there is any update i.e. updated transaction id or updated reserved id 2. If there is failure to execute BeginExecute api and the connection is reserved conn then check if shard session can be reset and execute ReserveBeginExecute api Signed-off-by: Harshit Gangal --- go/vt/vtgate/scatter_conn.go | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/scatter_conn.go b/go/vt/vtgate/scatter_conn.go index 12565c6af09..e63f5499f80 100644 --- a/go/vt/vtgate/scatter_conn.go +++ b/go/vt/vtgate/scatter_conn.go @@ -227,13 +227,25 @@ func (stc *ScatterConn) ExecuteMultiShard( innerqr, reservedID, alias, err = qs.ReserveExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, 0 /*transactionId*/, opts) } if err != nil { - return nil, err + return info.updateReservedID(reservedID, alias), err } } case begin: innerqr, transactionID, alias, err = qs.BeginExecute(ctx, rs.Target, session.Savepoints, queries[i].Sql, queries[i].BindVariables, info.reservedID, opts) if err != nil { - return info.updateTransactionID(transactionID, alias), err + if transactionID != 0 { + return info.updateTransactionID(transactionID, alias), err + } + shouldRetry := checkAndResetShardSession(info, err, session) + if shouldRetry { + // we seem to have lost our connection. if it was a reserved connection, let's try to recreate it + info.actionNeeded = reserveBegin + innerqr, transactionID, reservedID, alias, err = qs.ReserveBeginExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, opts) + } + if err != nil { + return info.updateTransactionAndReservedID(transactionID, reservedID, alias), err + } + } case reserve: innerqr, reservedID, alias, err = qs.ReserveExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, info.transactionID, opts) @@ -727,14 +739,26 @@ type shardActionInfo struct { } func (sai *shardActionInfo) updateTransactionID(txID int64, alias *topodatapb.TabletAlias) *shardActionInfo { + if txID == 0 { + // As transaction id is ZERO, there is nothing to update in session shard sessions. + return nil + } return sai.updateTransactionAndReservedID(txID, sai.reservedID, alias) } func (sai *shardActionInfo) updateReservedID(rID int64, alias *topodatapb.TabletAlias) *shardActionInfo { + if rID == 0 { + // As reserved id is ZERO, there is nothing to update in session shard sessions. + return nil + } return sai.updateTransactionAndReservedID(sai.transactionID, rID, alias) } func (sai *shardActionInfo) updateTransactionAndReservedID(txID int64, rID int64, alias *topodatapb.TabletAlias) *shardActionInfo { + if txID == 0 && rID == 0 { + // As transaction id and reserved id is ZERO, there is nothing to update in session shard sessions. + return nil + } newInfo := *sai newInfo.reservedID = rID newInfo.transactionID = txID From 51644530f640e11f762e4933eed162a1db333035 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 9 Mar 2021 19:02:50 +0530 Subject: [PATCH 07/49] return code_aborted if connection not found in case of Begin with reserve connection Signed-off-by: Harshit Gangal --- go/vt/vttablet/tabletserver/tx_pool.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/vt/vttablet/tabletserver/tx_pool.go b/go/vt/vttablet/tabletserver/tx_pool.go index 1a884038939..7962207137b 100644 --- a/go/vt/vttablet/tabletserver/tx_pool.go +++ b/go/vt/vttablet/tabletserver/tx_pool.go @@ -231,6 +231,9 @@ func (tp *TxPool) Begin(ctx context.Context, options *querypb.ExecuteOptions, re var err error if reservedID != 0 { conn, err = tp.scp.GetAndLock(reservedID, "start transaction on reserve conn") + if err != nil { + return nil, "", vterrors.Errorf(vtrpcpb.Code_ABORTED, "transaction %d: %v", reservedID, err) + } } else { immediateCaller := callerid.ImmediateCallerIDFromContext(ctx) effectiveCaller := callerid.EffectiveCallerIDFromContext(ctx) From 453f5a890ed66f187a0b8e1d93b2346b34ff0e87 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 9 Mar 2021 19:32:00 +0530 Subject: [PATCH 08/49] make e2e test to run faster Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/unsharded/main_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index 2dd99bca9b9..4dc3fd70287 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -114,6 +114,7 @@ func TestMain(m *testing.M) { SchemaSQL: SchemaSQL, VSchema: VSchema, } + clusterInstance.VtTabletExtraArgs = []string{"-queryserver-config-transaction-timeout", "3"} if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { return 1 } @@ -232,7 +233,7 @@ func TestReservedConnDML(t *testing.T) { exec(t, conn, `insert into allDefaults () values ()`) exec(t, conn, `commit`) - time.Sleep(35 * time.Second) + time.Sleep(6 * time.Second) exec(t, conn, `begin`) exec(t, conn, `insert into allDefaults () values ()`) From 5115a9402052f1a2eb0c06d9a7319087c23afc59 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Fri, 12 Mar 2021 11:42:25 +0530 Subject: [PATCH 09/49] fix unit test Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor_dml_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/go/vt/vtgate/executor_dml_test.go b/go/vt/vtgate/executor_dml_test.go index 11bee5a489c..1219fd4c96f 100644 --- a/go/vt/vtgate/executor_dml_test.go +++ b/go/vt/vtgate/executor_dml_test.go @@ -1747,7 +1747,8 @@ func TestReservedConnDML(t *testing.T) { defer QueryLogger.Unsubscribe(logChan) ctx := context.Background() - session := NewAutocommitSession(&vtgatepb.Session{EnableSystemSettings: true}) + *sysVarSetEnabled = true + session := NewAutocommitSession(&vtgatepb.Session{}) _, err := executor.Execute(ctx, "TestReservedConnDML", session, "use "+KsTestUnsharded, nil) require.NoError(t, err) @@ -1778,7 +1779,7 @@ func TestReservedConnDML(t *testing.T) { _, err = executor.Execute(ctx, "TestReservedConnDML", session, "begin", nil) require.NoError(t, err) - sbc.EphemeralShardErr = mysql.NewSQLError(mysql.CRServerGone, mysql.SSNetError, "connection gone") + sbc.EphemeralShardErr = mysql.NewSQLError(mysql.CRServerGone, mysql.SSUnknownSQLState, "connection gone") // as the first time the query fails due to connection loss i.e. reserved conn lost. It will be recreated to set statement will be executed again. wantQueries = append(wantQueries, &querypb.BoundQuery{Sql: "set @@default_week_format = 1", BindVariables: map[string]*querypb.BindVariable{}}, From 9ced2ddcea919b17413702f531b120c15a0d66fd Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 17 Mar 2021 15:02:39 +0530 Subject: [PATCH 10/49] add current_user parse test Signed-off-by: Harshit Gangal --- go/vt/sqlparser/parse_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/vt/sqlparser/parse_test.go b/go/vt/sqlparser/parse_test.go index 6878ebe4bda..f64a3b072bb 100644 --- a/go/vt/sqlparser/parse_test.go +++ b/go/vt/sqlparser/parse_test.go @@ -2080,6 +2080,9 @@ func TestKeywords(t *testing.T) { }, { input: "select Variables from t", output: "select `Variables` from t", + }, { + input: "select current_user, current_user() from dual", + output: "select current_user(), current_user() from dual", }} for _, tcase := range validSQL { From 77a633b1279e8c38f63ae2a2edaa99e66834dfa6 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 17 Mar 2021 15:04:34 +0530 Subject: [PATCH 11/49] added parsing support for current_user function Signed-off-by: Harshit Gangal --- go/vt/sqlparser/sql.go | 5895 ++++++++++++++++++++-------------------- go/vt/sqlparser/sql.y | 22 +- 2 files changed, 2961 insertions(+), 2956 deletions(-) diff --git a/go/vt/sqlparser/sql.go b/go/vt/sqlparser/sql.go index fcd8343aa4e..6c521afb8b9 100644 --- a/go/vt/sqlparser/sql.go +++ b/go/vt/sqlparser/sql.go @@ -1036,7 +1036,7 @@ var yyExca = [...]int{ 1, -1, -2, 0, -1, 42, - 163, 906, + 163, 907, -2, 89, -1, 43, 1, 107, @@ -1073,1262 +1073,642 @@ var yyExca = [...]int{ 252, 113, 300, 113, -2, 334, - -1, 549, - 149, 917, - -2, 913, -1, 550, 149, 918, -2, 914, - -1, 567, + -1, 551, + 149, 919, + -2, 915, + -1, 568, 55, 531, -2, 543, - -1, 568, + -1, 569, 55, 532, -2, 544, - -1, 588, - 117, 1244, - -2, 82, -1, 589, - 117, 1131, + 117, 1245, + -2, 82, + -1, 590, + 117, 1132, -2, 83, - -1, 595, - 117, 1179, - -2, 891, - -1, 729, - 117, 1073, - -2, 888, - -1, 761, + -1, 596, + 117, 1180, + -2, 892, + -1, 730, + 117, 1074, + -2, 889, + -1, 762, 174, 36, 179, 36, -2, 241, - -1, 840, + -1, 841, 1, 372, 451, 372, -2, 113, - -1, 1055, + -1, 1057, 1, 268, 451, 268, -2, 113, - -1, 1128, + -1, 1130, 168, 230, 169, 230, -2, 319, - -1, 1137, + -1, 1139, 174, 37, 179, 37, -2, 242, - -1, 1331, - 149, 920, - -2, 916, - -1, 1421, + -1, 1333, + 149, 921, + -2, 917, + -1, 1423, 73, 64, 81, 64, -2, 68, - -1, 1442, + -1, 1444, 1, 269, 451, 269, -2, 113, - -1, 1829, - 5, 785, - 18, 785, - 20, 785, - 32, 785, - 82, 785, + -1, 1831, + 5, 786, + 18, 786, + 20, 786, + 32, 786, + 82, 786, -2, 569, - -1, 2041, - 45, 859, - -2, 857, + -1, 2043, + 45, 860, + -2, 858, } const yyPrivate = 57344 -const yyLast = 26381 +const yyLast = 26340 var yyAct = [...]int{ - 549, 2127, 1876, 2114, 2041, 1747, 2091, 2054, 493, 1645, - 1987, 1716, 1965, 893, 79, 3, 1809, 1504, 1810, 522, - 1439, 1613, 1368, 1720, 508, 1873, 1003, 1646, 1354, 1806, - 1474, 959, 491, 1010, 1459, 1704, 1703, 1632, 1479, 1418, - 1821, 852, 142, 1768, 1573, 891, 1153, 173, 1325, 593, - 185, 1317, 458, 185, 733, 1246, 791, 1135, 474, 1259, - 185, 1502, 128, 1696, 1481, 77, 1047, 1040, 1031, 569, - 1400, 1370, 756, 1407, 1008, 1013, 1033, 31, 997, 495, - 1351, 554, 1294, 1551, 1142, 740, 1037, 1482, 474, 1030, - 737, 474, 185, 474, 741, 484, 1225, 762, 757, 758, - 1383, 590, 1046, 1423, 1044, 75, 1020, 1262, 563, 172, - 1470, 833, 759, 111, 112, 1127, 560, 769, 972, 1460, - 74, 8, 481, 7, 105, 145, 106, 973, 6, 1739, - 1738, 1989, 1533, 1365, 1366, 1212, 2083, 1611, 2038, 1280, - 1944, 2016, 2015, 1852, 795, 1960, 794, 534, 1961, 540, - 541, 538, 539, 555, 537, 536, 535, 2133, 575, 579, - 113, 577, 2088, 734, 542, 543, 2126, 1486, 185, 107, - 76, 436, 2065, 2117, 1877, 1521, 796, 2087, 185, 1785, - 846, 2064, 1906, 185, 482, 483, 33, 793, 1484, 68, - 37, 38, 587, 174, 175, 176, 748, 1612, 1540, 80, - 807, 808, 1539, 811, 812, 813, 814, 594, 97, 817, - 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, - 828, 829, 830, 831, 1835, 485, 1328, 751, 772, 750, - 107, 749, 1433, 773, 82, 83, 84, 85, 86, 87, - 102, 178, 179, 180, 1836, 1837, 889, 797, 798, 799, - 1048, 1676, 1049, 449, 1675, 1367, 462, 1677, 862, 804, - 67, 810, 450, 102, 94, 809, 752, 1483, 1434, 1435, - 98, 860, 447, 99, 100, 871, 872, 553, 552, 174, - 175, 176, 171, 1687, 174, 175, 176, 1453, 166, 1937, - 1749, 1897, 33, 34, 35, 68, 37, 38, 107, 1281, - 1282, 1283, 873, 1895, 461, 472, 874, 871, 872, 2067, - 1279, 444, 72, 108, 1769, 476, 470, 39, 65, 66, - 456, 63, 1202, 150, 888, 1721, 1536, 64, 1503, 2028, - 921, 920, 930, 931, 923, 924, 925, 926, 927, 928, - 929, 922, 1743, 1226, 932, 2116, 863, 887, 834, 1744, - 1234, 2084, 1235, 1236, 868, 1231, 52, 1771, 880, 861, - 882, 1750, 462, 1203, 1680, 1204, 67, 102, 167, 866, - 867, 462, 864, 865, 841, 1752, 462, 147, 1548, 148, - 816, 815, 1230, 1955, 771, 1751, 1228, 1112, 165, 437, - 438, 439, 101, 454, 455, 465, 780, 879, 881, 451, - 453, 466, 440, 441, 468, 467, 1851, 443, 442, 1232, - 461, 446, 463, 2012, 1773, 101, 1777, 753, 1772, 461, - 1770, 1505, 771, 1229, 461, 1775, 1401, 789, 778, 1485, - 788, 787, 786, 1538, 1774, 785, 185, 784, 42, 45, - 48, 47, 50, 783, 62, 2063, 151, 1776, 1778, 782, - 875, 878, 777, 462, 1121, 790, 156, 1956, 1555, 474, - 474, 474, 844, 738, 1424, 885, 2134, 2103, 765, 51, - 71, 70, 738, 104, 60, 61, 49, 474, 474, 855, - 856, 857, 858, 859, 764, 738, 845, 771, 781, 736, - 170, 771, 745, 903, 877, 1753, 2131, 1141, 1140, 890, - 2055, 461, 69, 581, 1527, 894, 895, 1614, 1616, 876, - 53, 54, 2004, 55, 56, 57, 58, 2068, 770, 101, - 779, 1239, 897, 800, 1713, 764, 767, 768, 1535, 738, - 1794, 771, 1793, 761, 765, 806, 464, 2029, 1792, 746, - 1731, 771, 435, 459, 1214, 1213, 1215, 1216, 1217, 177, - 1523, 1592, 760, 185, 1553, 2045, 770, 143, 460, 1552, - 1553, 1547, 774, 764, 1546, 1552, 944, 945, 838, 1589, - 942, 1001, 775, 1926, 1834, 1637, 1581, 1513, 474, 1429, - 869, 185, 1024, 185, 185, 957, 474, 850, 1000, 1440, - 776, 932, 474, 922, 884, 1672, 932, 1379, 854, 590, - 906, 960, 904, 1615, 1276, 2020, 886, 905, 69, 921, - 920, 930, 931, 923, 924, 925, 926, 927, 928, 929, - 922, 770, 1029, 932, 912, 770, 792, 774, 764, 998, - 1819, 1260, 764, 767, 768, 1263, 738, 775, 1227, 1014, - 761, 765, 2129, 847, 848, 2130, 840, 2128, 835, 913, - 836, 2005, 2003, 837, 975, 977, 979, 981, 983, 985, - 986, 1352, 1050, 976, 978, 770, 982, 984, 1574, 987, - 911, 909, 907, 1522, 995, 770, 839, 805, 925, 926, - 927, 928, 929, 922, 1787, 485, 932, 912, 1116, 944, - 945, 174, 175, 176, 970, 1319, 923, 924, 925, 926, - 927, 928, 929, 922, 90, 594, 932, 944, 945, 1520, - 853, 144, 149, 146, 152, 153, 154, 155, 157, 158, - 159, 160, 1518, 1006, 1009, 1301, 780, 161, 162, 163, - 164, 1450, 778, 185, 174, 175, 176, 1108, 909, 1299, - 1300, 1298, 1701, 1451, 1685, 185, 1261, 1117, 1118, 91, - 1264, 1320, 2048, 744, 912, 1381, 1352, 1002, 1599, 1017, - 474, 67, 1137, 2135, 1587, 169, 910, 911, 909, 2121, - 1146, 1515, 1586, 1297, 1150, 1384, 1385, 474, 474, 2120, - 474, 1147, 474, 474, 912, 474, 474, 474, 474, 474, - 474, 1943, 1515, 1012, 1692, 1519, 1942, 910, 911, 909, - 474, 910, 911, 909, 185, 1186, 1181, 1182, 1119, 1120, - 1289, 1291, 1292, 1857, 1133, 912, 1517, 1380, 1126, 912, - 1199, 2110, 1290, 1700, 1155, 1699, 1156, 1145, 1158, 1160, - 2136, 474, 1164, 1166, 1168, 1170, 1172, 2118, 2099, 185, - 1489, 564, 910, 911, 909, 185, 1107, 2077, 185, 1245, - 747, 185, 1222, 1144, 1183, 1114, 910, 911, 909, 743, - 912, 1207, 185, 1206, 185, 2119, 1189, 1190, 1124, 1122, - 1123, 1136, 1195, 1196, 912, 1588, 474, 474, 185, 474, - 474, 185, 474, 474, 1796, 1143, 1143, 921, 920, 930, - 931, 923, 924, 925, 926, 927, 928, 929, 922, 1205, - 1248, 932, 1251, 1221, 1253, 1219, 1255, 1256, 1257, 1258, - 2108, 910, 911, 909, 1566, 1567, 1568, 1197, 1191, 1789, - 1184, 1266, 1267, 1759, 1269, 1270, 1209, 1272, 1273, 912, - 1265, 1240, 1797, 1318, 1188, 1295, 1187, 1162, 2109, 1045, - 1978, 1940, 1321, 921, 920, 930, 931, 923, 924, 925, - 926, 927, 928, 929, 922, 1914, 474, 932, 910, 911, - 909, 1220, 580, 1218, 1798, 750, 107, 749, 174, 175, - 176, 1329, 1679, 1709, 1340, 1343, 912, 1322, 1323, 1697, - 1353, 174, 175, 176, 1208, 1497, 1563, 1333, 1334, 474, - 474, 1274, 1531, 1530, 1335, 1296, 1249, 174, 175, 176, - 185, 1495, 174, 175, 176, 1210, 1200, 1331, 174, 175, - 176, 1198, 474, 1330, 1194, 1193, 1250, 1192, 1746, 185, - 564, 960, 474, 1862, 2102, 76, 185, 585, 185, 2010, - 1375, 1862, 2061, 1862, 2046, 2009, 185, 185, 1329, 1909, - 1359, 1360, 1875, 474, 1862, 564, 474, 1633, 582, 583, - 1419, 1862, 2018, 1958, 564, 1723, 590, 474, 1712, 590, - 1515, 564, 1924, 564, 1332, 1862, 1867, 1849, 1848, 1425, - 1284, 1285, 1286, 1287, 1331, 1845, 1846, 1845, 1844, 1425, - 1398, 1392, 564, 1448, 1394, 33, 921, 920, 930, 931, - 923, 924, 925, 926, 927, 928, 929, 922, 1443, 1633, - 932, 1393, 564, 1424, 1740, 1461, 1462, 1463, 1111, 1725, - 1640, 1444, 474, 1718, 1719, 1404, 550, 1374, 1404, 564, - 1494, 1496, 1807, 1422, 1945, 1338, 1339, 1386, 1396, 1447, - 1426, 1818, 1641, 474, 908, 564, 1666, 1476, 1428, 474, - 1426, 1516, 1427, 1146, 1424, 1146, 1431, 1430, 1424, 1111, - 1110, 1056, 1055, 1514, 33, 1446, 1445, 78, 1818, 67, - 1403, 1921, 594, 908, 33, 594, 186, 1818, 2019, 186, - 1392, 1946, 1947, 1948, 475, 2053, 186, 1862, 1847, 1404, - 1432, 1604, 1603, 474, 557, 1318, 1392, 1501, 1336, 1337, - 1318, 1318, 1342, 1345, 1346, 1515, 1515, 1498, 1477, 1177, - 1511, 1994, 1512, 1382, 475, 1493, 1487, 475, 186, 475, - 1404, 1490, 1438, 1488, 1472, 1473, 1363, 1358, 1238, 1042, - 1361, 1362, 1392, 755, 1507, 185, 1510, 1477, 67, 185, - 185, 185, 185, 185, 1506, 754, 1526, 1524, 67, 185, - 185, 1528, 1529, 185, 772, 1525, 1178, 1179, 1180, 773, - 67, 1967, 1874, 1932, 1113, 1475, 1745, 1508, 67, 1143, - 1471, 185, 185, 185, 1465, 511, 510, 513, 514, 515, - 516, 1478, 1464, 1224, 512, 185, 517, 1138, 185, 474, - 1134, 1109, 92, 1706, 186, 488, 1409, 1412, 1413, 1414, - 1410, 171, 1411, 1415, 186, 1748, 1822, 1823, 1968, 186, - 1705, 1557, 1949, 1486, 1174, 1822, 1823, 1561, 2123, 2115, - 1840, 1534, 916, 1825, 919, 1807, 1714, 1277, 1295, 1242, - 933, 934, 935, 936, 937, 938, 939, 1556, 917, 918, - 915, 921, 920, 930, 931, 923, 924, 925, 926, 927, - 928, 929, 922, 1828, 1706, 932, 1950, 1951, 1175, 1176, - 1576, 1827, 1654, 1653, 1577, 1409, 1412, 1413, 1414, 1410, - 2105, 1411, 1415, 1657, 185, 1584, 1585, 1659, 1658, 1413, - 1414, 1591, 185, 2086, 1594, 1595, 1011, 1799, 1296, 1622, - 1655, 1569, 1601, 1925, 1602, 1656, 1865, 1605, 1606, 1607, - 1608, 1609, 1631, 1630, 185, 2073, 2070, 2107, 2090, 2092, - 96, 1619, 2098, 1620, 2097, 185, 185, 185, 185, 185, - 555, 1621, 1647, 1626, 1582, 1642, 2042, 185, 2040, 1237, - 551, 185, 1710, 802, 185, 185, 801, 1004, 185, 185, - 185, 1598, 1705, 1635, 896, 1664, 1348, 1638, 1733, 1005, - 998, 1678, 1610, 1618, 1919, 1732, 168, 1662, 1663, 181, - 1349, 1454, 1583, 1455, 1456, 1457, 1458, 1625, 1684, 108, - 2050, 1691, 2049, 1667, 1636, 1992, 1509, 1669, 1634, 1466, - 1467, 1468, 1469, 1152, 1649, 1650, 1151, 1652, 1139, 1248, - 1690, 1377, 1693, 1694, 1695, 1681, 1491, 474, 1241, 1660, - 1688, 1689, 1665, 570, 1648, 2011, 1670, 1651, 1962, 1673, - 474, 1384, 1385, 1417, 558, 559, 474, 571, 561, 474, - 1629, 1146, 1722, 2112, 1600, 1917, 474, 1682, 1628, 2111, - 1726, 570, 2095, 2074, 1918, 1861, 1499, 1728, 1737, 1698, - 1015, 1016, 573, 562, 572, 571, 185, 78, 1802, 1633, - 1708, 1593, 1623, 1624, 1009, 1707, 1590, 1736, 1025, 1735, - 2125, 2124, 186, 1578, 1579, 474, 185, 1018, 567, 568, - 573, 1126, 572, 1331, 2125, 2043, 1938, 1378, 1727, 1330, - 557, 76, 81, 73, 1596, 475, 475, 475, 1, 445, - 1364, 996, 474, 457, 2113, 1211, 1734, 1201, 1318, 1878, - 1964, 1868, 1492, 475, 475, 1765, 1702, 1480, 763, 133, - 1754, 1441, 1442, 2057, 89, 731, 88, 1762, 1763, 766, - 1767, 883, 1500, 2002, 1959, 1758, 1766, 1686, 474, 1452, - 1756, 1936, 1757, 1839, 1683, 2047, 1062, 1060, 185, 1764, - 1786, 1061, 1780, 1059, 1064, 1063, 1058, 1278, 474, 1779, - 471, 1416, 1051, 1019, 474, 474, 803, 1850, 1449, 1647, - 1808, 1765, 1275, 1532, 452, 870, 448, 940, 1627, 1674, - 591, 1811, 584, 1813, 1795, 95, 2096, 185, 2071, 186, - 2069, 2039, 1814, 930, 931, 923, 924, 925, 926, 927, - 928, 929, 922, 1817, 1988, 932, 2072, 521, 2037, 2106, - 2089, 1816, 1826, 1829, 475, 1376, 1007, 186, 1916, 186, - 186, 1801, 475, 1830, 1597, 1832, 1831, 1833, 475, 1842, - 1843, 1858, 969, 1350, 185, 185, 1034, 494, 1288, 474, - 509, 506, 507, 1838, 1387, 1639, 914, 492, 486, 1026, - 1864, 1408, 185, 1406, 1405, 1243, 1038, 184, 1824, 1853, - 469, 1854, 1820, 1032, 1391, 1537, 1742, 184, 1869, 1879, - 474, 474, 474, 566, 185, 1805, 93, 1347, 1872, 2027, - 1905, 1788, 1855, 1856, 1866, 1908, 1871, 565, 59, 36, - 578, 578, 478, 1863, 2082, 899, 574, 30, 29, 184, - 28, 23, 946, 947, 948, 949, 950, 951, 952, 953, - 954, 955, 22, 1887, 21, 1803, 20, 1889, 1884, 1885, - 19, 25, 18, 17, 1893, 16, 103, 46, 1898, 1899, - 43, 41, 921, 920, 930, 931, 923, 924, 925, 926, - 927, 928, 929, 922, 1913, 110, 932, 1647, 109, 44, - 40, 842, 1915, 27, 26, 15, 14, 13, 1920, 12, - 11, 1922, 1923, 10, 9, 1927, 1929, 5, 4, 186, - 902, 1928, 24, 958, 2, 184, 0, 0, 0, 0, - 0, 186, 474, 474, 1934, 184, 0, 0, 0, 1935, - 184, 0, 0, 1953, 0, 474, 475, 0, 474, 1939, - 0, 1941, 166, 1888, 0, 1952, 1963, 0, 0, 0, - 0, 1966, 1971, 475, 475, 0, 475, 1957, 475, 475, - 0, 475, 475, 475, 475, 475, 475, 108, 0, 0, - 0, 474, 474, 474, 185, 1969, 475, 150, 0, 0, - 186, 0, 1981, 1983, 1984, 474, 1970, 474, 0, 0, - 0, 0, 0, 474, 0, 0, 1985, 0, 1995, 1982, - 1993, 1811, 1997, 0, 2000, 1811, 0, 475, 0, 1986, - 1991, 1907, 0, 0, 0, 186, 0, 185, 0, 0, - 2007, 186, 2008, 2006, 186, 0, 0, 186, 474, 185, - 0, 147, 0, 148, 485, 0, 2014, 2017, 186, 2021, - 186, 1930, 165, 0, 1931, 1903, 0, 1933, 0, 0, - 0, 0, 475, 475, 186, 475, 475, 186, 475, 475, - 0, 2023, 2024, 2025, 2026, 0, 2030, 2036, 2031, 2032, - 2033, 2044, 2034, 2035, 1811, 0, 0, 0, 0, 0, - 474, 474, 1977, 0, 0, 0, 2051, 0, 0, 0, - 0, 0, 2056, 1966, 2058, 0, 0, 0, 0, 0, - 151, 0, 0, 0, 0, 1999, 474, 0, 2066, 0, - 156, 2001, 1647, 2075, 474, 0, 2062, 0, 0, 2078, - 0, 0, 0, 0, 0, 2081, 1902, 2085, 0, 0, - 0, 0, 475, 0, 2094, 2093, 0, 0, 0, 1990, - 485, 0, 0, 0, 0, 0, 0, 0, 2104, 0, - 0, 0, 0, 921, 920, 930, 931, 923, 924, 925, - 926, 927, 928, 929, 922, 475, 475, 932, 2100, 2101, - 0, 0, 0, 0, 0, 0, 186, 2122, 0, 0, - 0, 0, 0, 184, 0, 0, 0, 2132, 475, 0, - 0, 0, 0, 0, 0, 186, 0, 0, 475, 0, - 0, 0, 186, 0, 186, 0, 0, 0, 0, 0, - 0, 143, 186, 186, 0, 0, 0, 1890, 1891, 475, - 1892, 0, 475, 1894, 1901, 1896, 0, 0, 0, 0, - 0, 0, 0, 475, 921, 920, 930, 931, 923, 924, - 925, 926, 927, 928, 929, 922, 0, 0, 932, 920, - 930, 931, 923, 924, 925, 926, 927, 928, 929, 922, - 1293, 0, 932, 1302, 1303, 1304, 1305, 1306, 1307, 1308, - 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1900, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 475, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 184, 0, 0, 0, 0, 0, 0, 0, 0, 475, - 0, 0, 0, 0, 578, 475, 0, 0, 0, 0, - 1355, 0, 0, 0, 0, 0, 0, 1575, 184, 0, - 184, 1041, 921, 920, 930, 931, 923, 924, 925, 926, - 927, 928, 929, 922, 0, 0, 932, 921, 920, 930, - 931, 923, 924, 925, 926, 927, 928, 929, 922, 475, - 0, 932, 0, 0, 0, 144, 149, 146, 152, 153, + 550, 2129, 2116, 1878, 2043, 1749, 2093, 2056, 493, 1647, + 1989, 1718, 1967, 894, 79, 3, 1811, 1506, 1812, 522, + 1441, 1615, 1370, 1875, 561, 1648, 508, 1808, 1356, 1005, + 1476, 960, 1722, 1012, 1461, 1706, 734, 1634, 491, 1481, + 1705, 853, 142, 1823, 1770, 1420, 1575, 173, 1327, 1261, + 185, 1319, 458, 185, 1504, 1137, 792, 1248, 474, 594, + 185, 128, 757, 1698, 892, 77, 1049, 1483, 1042, 1033, + 1402, 570, 1409, 1010, 1015, 1353, 1035, 1372, 999, 495, + 1296, 1553, 741, 763, 1144, 555, 1330, 738, 474, 31, + 1032, 474, 185, 474, 1039, 484, 1484, 1385, 1227, 742, + 1472, 591, 758, 759, 1048, 1425, 1046, 1022, 564, 75, + 1129, 1155, 760, 1264, 111, 112, 770, 834, 8, 481, + 973, 105, 145, 74, 106, 7, 172, 976, 6, 1741, + 1740, 1535, 1991, 1214, 80, 1613, 1462, 1367, 1368, 2085, + 1282, 2040, 1946, 1854, 2018, 2017, 1962, 796, 795, 1963, + 2135, 2090, 2128, 735, 1488, 113, 76, 576, 580, 2067, + 2119, 578, 1879, 1523, 2089, 556, 107, 2066, 185, 82, + 83, 84, 85, 86, 87, 1486, 797, 1787, 185, 1908, + 847, 482, 483, 185, 749, 1614, 33, 794, 436, 68, + 37, 38, 1838, 1839, 588, 174, 175, 176, 1542, 1837, + 808, 809, 1541, 812, 813, 814, 815, 171, 1435, 818, + 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, + 829, 830, 831, 832, 595, 485, 751, 107, 773, 750, + 1436, 1437, 774, 1050, 535, 1051, 541, 542, 539, 540, + 462, 538, 537, 536, 752, 554, 1114, 798, 799, 800, + 166, 543, 544, 553, 1485, 811, 863, 861, 805, 1369, + 67, 1717, 102, 178, 179, 180, 1455, 1678, 872, 873, + 1677, 753, 166, 1679, 881, 108, 883, 130, 890, 174, + 175, 176, 810, 1127, 1689, 150, 1751, 1939, 461, 2069, + 1899, 1897, 102, 167, 472, 107, 1281, 108, 476, 130, + 1283, 1284, 1285, 470, 874, 1538, 1723, 150, 875, 872, + 873, 97, 1204, 880, 882, 1505, 140, 1236, 1228, 1237, + 1238, 129, 2030, 922, 921, 931, 932, 924, 925, 926, + 927, 928, 929, 930, 923, 1771, 1233, 933, 140, 147, + 2118, 148, 835, 129, 864, 862, 1131, 1132, 139, 138, + 165, 1745, 888, 1205, 2086, 1206, 889, 1752, 1746, 1754, + 869, 147, 842, 148, 1550, 462, 102, 94, 1131, 1132, + 139, 138, 165, 98, 867, 868, 99, 100, 1773, 865, + 866, 462, 817, 816, 1753, 1230, 2014, 1232, 772, 1957, + 1234, 1507, 781, 779, 1403, 790, 789, 788, 134, 1133, + 141, 787, 1130, 786, 135, 136, 1853, 785, 151, 784, + 878, 783, 778, 461, 101, 170, 1487, 754, 156, 1557, + 134, 1133, 141, 1123, 1130, 877, 135, 136, 1231, 461, + 151, 2065, 791, 1540, 1958, 1775, 185, 1779, 1426, 1774, + 156, 1772, 845, 2105, 101, 2133, 1777, 739, 462, 739, + 876, 879, 766, 737, 2136, 1776, 739, 886, 104, 474, + 474, 474, 1143, 1142, 846, 765, 746, 772, 1778, 1780, + 1616, 1618, 582, 1755, 1529, 2006, 1241, 474, 474, 856, + 857, 858, 859, 860, 782, 780, 2057, 772, 898, 801, + 1715, 772, 1537, 904, 1796, 1795, 461, 2070, 1794, 891, + 747, 1733, 69, 922, 921, 931, 932, 924, 925, 926, + 927, 928, 929, 930, 923, 1555, 772, 933, 101, 143, + 1554, 1525, 771, 435, 895, 896, 177, 1442, 775, 765, + 2031, 2047, 1549, 1928, 1555, 1548, 945, 946, 776, 1554, + 1836, 143, 1216, 1215, 1217, 1218, 1219, 1639, 1594, 933, + 1583, 1515, 1431, 1026, 185, 958, 777, 851, 174, 175, + 176, 923, 1576, 839, 933, 1674, 1617, 807, 137, 1262, + 943, 1381, 1003, 772, 911, 912, 910, 1591, 1278, 474, + 131, 870, 185, 132, 185, 185, 885, 474, 913, 1002, + 137, 2131, 913, 474, 2132, 1265, 2130, 907, 887, 2022, + 591, 771, 131, 910, 905, 132, 90, 906, 765, 768, + 769, 793, 739, 961, 2007, 2005, 762, 766, 1694, 913, + 1821, 771, 1229, 848, 849, 771, 1052, 775, 765, 1031, + 1000, 841, 765, 768, 769, 761, 739, 776, 912, 910, + 762, 766, 1016, 836, 1524, 837, 908, 840, 838, 914, + 771, 91, 855, 1789, 1014, 913, 975, 978, 980, 982, + 983, 985, 987, 988, 979, 981, 1354, 984, 986, 1354, + 989, 1601, 997, 144, 149, 146, 152, 153, 154, 155, + 157, 158, 159, 160, 1263, 485, 945, 946, 1118, 161, + 162, 163, 164, 1004, 971, 144, 149, 146, 152, 153, + 154, 155, 157, 158, 159, 160, 1522, 771, 1452, 806, + 1266, 161, 162, 163, 164, 945, 946, 174, 175, 176, + 1453, 1321, 1520, 595, 1008, 1011, 924, 925, 926, 927, + 928, 929, 930, 923, 185, 781, 933, 779, 1110, 926, + 927, 928, 929, 930, 923, 1517, 185, 933, 1119, 1120, + 931, 932, 924, 925, 926, 927, 928, 929, 930, 923, + 2137, 474, 933, 1139, 854, 1589, 2050, 1687, 1517, 1521, + 1019, 1148, 1223, 1588, 2120, 1152, 2110, 1322, 474, 474, + 1303, 474, 1149, 474, 474, 1945, 474, 474, 474, 474, + 474, 474, 1519, 169, 1301, 1302, 1300, 1135, 911, 912, + 910, 474, 2121, 1944, 2111, 185, 1188, 1183, 1184, 1121, + 1122, 911, 912, 910, 1221, 745, 913, 1703, 1128, 1791, + 1859, 1201, 1568, 1569, 1570, 1702, 1147, 2138, 1798, 913, + 1222, 1701, 474, 67, 1386, 1387, 1491, 1185, 1211, 1224, + 185, 911, 912, 910, 1209, 1299, 185, 1208, 1207, 185, + 1247, 1199, 185, 1193, 1146, 1190, 174, 175, 176, 913, + 1681, 2123, 1116, 185, 1109, 185, 1125, 1191, 1192, 1590, + 1126, 1124, 1220, 1197, 1198, 1189, 1799, 474, 474, 185, + 474, 474, 185, 474, 474, 1145, 1145, 744, 1164, 1138, + 1157, 1047, 1158, 2122, 1160, 1162, 1210, 2112, 1166, 1168, + 1170, 1172, 1174, 1253, 2101, 1255, 2079, 1257, 1258, 1259, + 1260, 1250, 748, 1980, 1942, 911, 912, 910, 1383, 1916, + 1800, 1267, 921, 931, 932, 924, 925, 926, 927, 928, + 929, 930, 923, 913, 1320, 933, 1297, 1711, 1186, 581, + 1242, 1268, 1269, 1323, 1271, 1272, 1699, 1274, 1275, 1291, + 1293, 1294, 911, 912, 910, 1565, 1533, 474, 174, 175, + 176, 1292, 1499, 751, 107, 1532, 750, 174, 175, 176, + 913, 1497, 1331, 1251, 1212, 1342, 1345, 1200, 1196, 586, + 1382, 1355, 1195, 1194, 1324, 1325, 1748, 565, 1335, 1336, + 2012, 474, 474, 1864, 2104, 1337, 1298, 2011, 1276, 174, + 175, 176, 185, 1202, 1877, 911, 912, 910, 174, 175, + 176, 1864, 2063, 76, 474, 1725, 1332, 1252, 1333, 1864, + 2048, 185, 1714, 913, 474, 583, 584, 1376, 185, 1450, + 185, 1635, 1377, 1668, 961, 1864, 565, 1388, 185, 185, + 1331, 1426, 1361, 1362, 1820, 474, 1864, 2020, 474, 1338, + 1339, 1809, 1421, 1344, 1347, 1348, 1960, 565, 591, 474, + 1820, 591, 1517, 565, 1926, 565, 1864, 1869, 1923, 1334, + 1635, 1286, 1287, 1288, 1289, 1851, 1850, 1847, 1848, 1360, + 1847, 1846, 1363, 1364, 1400, 33, 1333, 1427, 1396, 1395, + 565, 1394, 565, 1426, 1742, 1446, 1427, 1113, 1727, 1406, + 1445, 511, 510, 513, 514, 515, 516, 1463, 1464, 1465, + 512, 909, 517, 78, 474, 1720, 1721, 551, 1406, 565, + 1518, 1449, 1496, 1498, 909, 565, 1340, 1341, 2021, 33, + 1405, 1398, 1996, 1424, 1864, 474, 1113, 1112, 1820, 1478, + 1849, 474, 1058, 1057, 33, 1148, 1429, 1148, 1428, 1406, + 1433, 1432, 1434, 1606, 1642, 1516, 1430, 1428, 1394, 67, + 2055, 1448, 1447, 1605, 1394, 1426, 1517, 186, 1500, 1384, + 186, 1503, 1365, 558, 1517, 475, 1643, 186, 1394, 1240, + 1406, 595, 1044, 756, 595, 474, 755, 1320, 67, 1969, + 1876, 1934, 1320, 1320, 1115, 1477, 1747, 1479, 1510, 1473, + 1513, 1467, 1514, 67, 1947, 475, 1474, 1475, 475, 186, + 475, 1466, 1490, 1489, 1440, 1492, 1495, 1226, 67, 1179, + 1140, 1526, 1508, 1509, 1136, 1111, 1479, 185, 1512, 92, + 1951, 185, 185, 185, 185, 185, 1708, 171, 1528, 1707, + 1527, 185, 185, 1530, 1531, 185, 773, 67, 1176, 1750, + 774, 1948, 1949, 1950, 1970, 1411, 1414, 1415, 1416, 1412, + 1145, 1413, 1417, 185, 185, 185, 1180, 1181, 1182, 1824, + 1825, 1488, 2107, 1480, 1952, 1953, 2125, 185, 1830, 2088, + 185, 474, 2117, 1708, 1842, 186, 488, 1827, 565, 1809, + 1829, 1716, 1177, 1178, 1279, 186, 1244, 1659, 1656, 1657, + 186, 1655, 1660, 1559, 1658, 1661, 1801, 1415, 1416, 1563, + 1624, 1013, 1456, 1927, 1457, 1458, 1459, 1460, 1867, 1633, + 1297, 1536, 1632, 2075, 2072, 2109, 2092, 1558, 2094, 2100, + 1468, 1469, 1470, 1471, 922, 921, 931, 932, 924, 925, + 926, 927, 928, 929, 930, 923, 1622, 2099, 933, 2044, + 1239, 2042, 1578, 552, 1623, 96, 1579, 1712, 1350, 803, + 802, 571, 1585, 1707, 897, 1735, 185, 1586, 1587, 2052, + 1006, 1734, 1351, 1593, 185, 572, 1596, 1597, 1686, 108, + 1298, 1571, 1007, 2051, 1603, 1994, 1604, 1511, 1154, 1607, + 1608, 1609, 1610, 1611, 1153, 1141, 185, 1921, 1017, 1018, + 574, 168, 573, 1379, 181, 1493, 1621, 185, 185, 185, + 185, 185, 1386, 1387, 1649, 1580, 1581, 1644, 1628, 185, + 1584, 1243, 2013, 185, 556, 1964, 185, 185, 1600, 1419, + 185, 185, 185, 559, 560, 562, 1598, 1666, 1631, 1640, + 2114, 1637, 1000, 1680, 1612, 2113, 1630, 2097, 2076, 1664, + 1665, 1620, 1920, 1863, 1501, 563, 78, 1919, 1627, 1804, + 1635, 2127, 2126, 1693, 1595, 1592, 1027, 1020, 1638, 1636, + 2127, 1669, 2045, 1940, 1380, 1671, 558, 1651, 1652, 81, + 1654, 76, 1692, 73, 1695, 1696, 1697, 1683, 1, 474, + 1662, 1250, 1690, 1691, 1667, 445, 571, 1650, 1366, 1672, + 1653, 1675, 474, 998, 457, 2115, 1213, 1203, 474, 1684, + 572, 474, 1880, 1148, 1724, 1966, 1602, 1870, 474, 1494, + 1704, 1482, 1728, 764, 133, 1443, 1444, 2059, 89, 1730, + 1739, 1700, 732, 568, 569, 574, 88, 573, 185, 767, + 884, 1502, 1710, 2004, 1625, 1626, 1011, 1961, 1688, 1738, + 1709, 1454, 1938, 186, 1841, 1685, 2049, 474, 185, 1064, + 1737, 1062, 1128, 1063, 1061, 1066, 1065, 1060, 1729, 1280, + 471, 1418, 1053, 1332, 1021, 1333, 475, 475, 475, 804, + 1852, 1736, 1451, 1277, 474, 1534, 452, 871, 448, 941, + 1320, 1629, 1676, 592, 475, 475, 585, 1767, 1815, 95, + 2098, 2073, 2071, 2041, 1990, 2074, 2039, 2108, 2091, 1764, + 1765, 1378, 1758, 1009, 1759, 1769, 1918, 1803, 1768, 1760, + 474, 1756, 1599, 970, 1352, 1036, 494, 1290, 509, 506, + 185, 1766, 1788, 507, 1389, 1782, 1641, 915, 492, 486, + 474, 1781, 1028, 1410, 1408, 1407, 474, 474, 1245, 1040, + 1826, 1649, 1810, 1767, 1822, 1034, 1393, 1539, 1744, 567, + 93, 1349, 2029, 1813, 1907, 1807, 566, 59, 36, 185, + 478, 186, 2084, 900, 1816, 575, 1411, 1414, 1415, 1416, + 1412, 30, 1413, 1417, 29, 1819, 1824, 1825, 28, 521, + 23, 22, 21, 20, 19, 1831, 475, 1828, 25, 186, + 18, 186, 186, 17, 475, 1832, 16, 1834, 103, 1835, + 475, 1844, 1845, 1860, 1833, 46, 185, 185, 43, 41, + 110, 474, 109, 44, 40, 1840, 843, 27, 26, 15, + 14, 1797, 1866, 13, 185, 12, 11, 10, 9, 184, + 5, 1855, 469, 4, 903, 24, 959, 1856, 2, 184, + 1871, 1881, 474, 474, 474, 0, 185, 1865, 1818, 0, + 0, 0, 0, 1790, 1857, 1858, 1911, 1868, 0, 1874, + 0, 0, 579, 579, 1873, 0, 0, 0, 0, 0, + 0, 184, 0, 947, 948, 949, 950, 951, 952, 953, + 954, 955, 956, 1890, 0, 1889, 0, 1805, 0, 1891, + 1886, 1887, 0, 0, 0, 0, 1895, 0, 0, 0, + 1900, 1901, 0, 922, 921, 931, 932, 924, 925, 926, + 927, 928, 929, 930, 923, 0, 1915, 933, 0, 1649, + 0, 0, 0, 0, 1917, 0, 0, 0, 1922, 0, + 0, 0, 0, 1924, 1925, 0, 1931, 1929, 0, 0, + 0, 186, 0, 1930, 0, 0, 0, 184, 0, 0, + 0, 0, 0, 186, 474, 474, 1936, 184, 0, 0, + 0, 1937, 184, 0, 0, 1955, 0, 474, 475, 0, + 474, 1941, 0, 1943, 0, 1954, 0, 0, 1965, 0, + 0, 0, 0, 1968, 1973, 475, 475, 0, 475, 1959, + 475, 475, 0, 475, 475, 475, 475, 475, 475, 0, + 0, 0, 0, 474, 474, 474, 185, 0, 475, 0, + 1971, 0, 186, 0, 1983, 1985, 1986, 474, 1972, 474, + 0, 0, 1979, 0, 0, 474, 0, 0, 1987, 0, + 1997, 1984, 1995, 1813, 1999, 0, 2002, 1813, 0, 475, + 0, 1988, 1993, 1909, 0, 2001, 0, 186, 0, 185, + 0, 2003, 2009, 186, 2010, 0, 186, 2008, 0, 186, + 474, 185, 0, 0, 0, 0, 485, 0, 2016, 2019, + 186, 2023, 186, 1932, 0, 0, 1933, 0, 0, 1935, + 0, 0, 0, 0, 475, 475, 186, 475, 475, 186, + 475, 475, 0, 2025, 2026, 2027, 2028, 0, 2032, 2038, + 2033, 2034, 2035, 2046, 2036, 2037, 1813, 0, 1892, 1893, + 0, 1894, 474, 474, 1896, 0, 1898, 0, 2053, 0, + 0, 0, 0, 0, 2058, 1968, 2060, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 474, 0, + 2068, 0, 0, 0, 1649, 2077, 474, 0, 2064, 0, + 0, 2080, 0, 0, 0, 0, 0, 2083, 0, 2087, + 0, 0, 0, 0, 475, 0, 2096, 2095, 0, 0, + 0, 1992, 485, 0, 0, 0, 0, 0, 0, 0, + 0, 2106, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 174, 175, 176, 0, 0, 475, 475, + 2102, 2103, 0, 0, 0, 0, 0, 0, 2124, 186, + 0, 0, 0, 0, 0, 184, 0, 0, 0, 2134, + 0, 475, 0, 0, 0, 0, 1910, 0, 186, 0, + 0, 475, 0, 0, 0, 186, 0, 186, 0, 0, + 0, 0, 0, 0, 0, 186, 186, 0, 0, 0, + 0, 0, 475, 449, 0, 475, 0, 1905, 0, 0, + 0, 0, 450, 0, 0, 0, 475, 0, 0, 0, + 0, 0, 447, 922, 921, 931, 932, 924, 925, 926, + 927, 928, 929, 930, 923, 0, 0, 933, 0, 0, + 0, 0, 1295, 0, 0, 1304, 1305, 1306, 1307, 1308, + 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, + 0, 444, 0, 0, 0, 0, 0, 0, 0, 0, + 456, 475, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, + 0, 0, 475, 0, 0, 0, 0, 579, 475, 0, + 0, 0, 0, 0, 1357, 0, 0, 0, 0, 0, + 0, 184, 462, 184, 1043, 922, 921, 931, 932, 924, + 925, 926, 927, 928, 929, 930, 923, 0, 0, 933, + 0, 0, 0, 1904, 0, 0, 0, 0, 0, 437, + 438, 439, 475, 454, 455, 465, 1761, 0, 0, 451, + 453, 466, 440, 441, 468, 467, 0, 443, 442, 0, + 461, 446, 463, 0, 0, 0, 922, 921, 931, 932, + 924, 925, 926, 927, 928, 929, 930, 923, 0, 0, + 933, 0, 166, 0, 186, 0, 0, 0, 186, 186, + 186, 186, 186, 0, 0, 0, 0, 0, 186, 186, + 0, 0, 186, 0, 0, 166, 0, 108, 0, 0, + 0, 520, 0, 0, 0, 0, 0, 150, 0, 0, + 186, 186, 186, 0, 0, 0, 0, 0, 0, 0, + 108, 0, 0, 0, 186, 0, 0, 186, 475, 0, + 150, 922, 921, 931, 932, 924, 925, 926, 927, 928, + 929, 930, 923, 0, 0, 933, 0, 0, 1682, 0, + 0, 0, 0, 184, 0, 0, 0, 0, 0, 473, + 1001, 147, 0, 148, 0, 184, 0, 0, 0, 0, + 0, 0, 165, 0, 0, 0, 464, 1903, 0, 0, + 0, 0, 0, 459, 147, 0, 148, 0, 0, 593, + 0, 0, 736, 1151, 743, 165, 0, 0, 460, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 183, 0, 0, 186, 0, 0, 0, 0, 1151, 1151, + 477, 186, 0, 0, 184, 0, 0, 0, 0, 0, + 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 156, 0, 0, 186, 0, 0, 0, 0, 0, 0, + 0, 0, 740, 151, 186, 186, 186, 186, 186, 184, + 0, 0, 0, 156, 0, 184, 186, 0, 184, 0, + 186, 1249, 0, 186, 186, 0, 0, 186, 186, 186, + 0, 0, 184, 1577, 184, 922, 921, 931, 932, 924, + 925, 926, 927, 928, 929, 930, 923, 0, 184, 933, + 0, 184, 0, 922, 921, 931, 932, 924, 925, 926, + 927, 928, 929, 930, 923, 0, 0, 933, 1572, 1573, + 1574, 0, 0, 0, 0, 0, 0, 0, 833, 0, + 0, 0, 0, 0, 0, 0, 475, 0, 844, 0, + 0, 143, 0, 850, 0, 0, 0, 0, 0, 475, + 0, 0, 0, 0, 0, 475, 0, 0, 475, 0, + 0, 0, 0, 0, 143, 475, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 579, 1249, 0, + 0, 0, 579, 579, 0, 186, 579, 579, 579, 0, + 0, 0, 1151, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 475, 186, 0, 0, 0, 0, + 0, 0, 579, 579, 579, 579, 579, 0, 0, 0, + 0, 1374, 0, 0, 0, 0, 0, 0, 0, 0, + 1902, 475, 0, 0, 0, 0, 0, 0, 0, 0, + 184, 0, 0, 0, 0, 0, 1249, 184, 0, 184, + 0, 0, 0, 0, 0, 0, 0, 184, 184, 0, + 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 475, 0, 0, + 0, 0, 0, 475, 475, 144, 149, 146, 152, 153, 154, 155, 157, 158, 159, 160, 0, 0, 0, 0, - 0, 161, 162, 163, 164, 0, 921, 920, 930, 931, - 923, 924, 925, 926, 927, 928, 929, 922, 0, 0, - 932, 186, 0, 0, 0, 186, 186, 186, 186, 186, - 0, 0, 0, 0, 0, 186, 186, 0, 0, 186, - 0, 0, 0, 0, 0, 0, 0, 0, 520, 0, - 0, 0, 0, 0, 0, 0, 0, 186, 186, 186, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 186, 0, 0, 186, 475, 921, 920, 930, 931, - 923, 924, 925, 926, 927, 928, 929, 922, 0, 0, - 932, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 184, 0, 0, 0, 0, 0, 473, 0, 0, 0, - 0, 0, 184, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 592, 0, 0, 735, - 1149, 742, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 186, 0, 0, 0, 0, 1149, 1149, 0, 186, 0, - 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 186, 186, 186, 186, 186, 184, 0, 0, 0, - 0, 0, 184, 186, 0, 184, 0, 186, 1247, 0, - 186, 186, 0, 0, 186, 186, 186, 0, 0, 184, - 0, 184, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 184, 0, 0, 184, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1079, 1570, 1571, 1572, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 999, 0, 475, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 475, 0, 0, 0, - 0, 0, 475, 0, 0, 475, 0, 0, 0, 0, - 0, 0, 475, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 578, 1247, 0, 0, 0, 578, - 578, 183, 186, 578, 578, 578, 0, 0, 0, 1149, - 0, 477, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 475, 186, 0, 0, 0, 0, 0, 578, 578, - 578, 578, 578, 0, 0, 0, 0, 1372, 0, 0, - 0, 0, 0, 739, 0, 0, 1067, 0, 475, 0, + 0, 161, 162, 163, 164, 0, 186, 0, 144, 149, + 146, 152, 153, 154, 155, 157, 158, 159, 160, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 922, 921, + 931, 932, 924, 925, 926, 927, 928, 929, 930, 923, + 0, 0, 933, 0, 0, 0, 0, 0, 0, 0, + 593, 593, 593, 186, 186, 0, 0, 0, 475, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 899, 901, + 0, 186, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1762, 1763, 0, 852, 0, 0, 475, + 475, 475, 0, 186, 0, 0, 0, 0, 1783, 1784, + 0, 1785, 1786, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1792, 1793, 922, 921, 931, 932, 924, 925, + 926, 927, 928, 929, 930, 923, 0, 0, 933, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, - 0, 0, 1247, 184, 0, 184, 0, 0, 0, 0, - 0, 0, 0, 184, 184, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 475, 0, 0, 0, 0, 1080, - 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 475, 0, 0, 0, 0, 0, - 475, 475, 0, 0, 0, 0, 0, 0, 0, 832, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 843, - 0, 0, 0, 186, 849, 1093, 1096, 1097, 1098, 1099, - 1100, 1101, 0, 1102, 1103, 1104, 1105, 1106, 1081, 1082, - 1083, 1084, 1065, 1066, 1094, 0, 1068, 0, 1069, 1070, - 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1085, 1086, - 1087, 1088, 1089, 1090, 1091, 1092, 0, 592, 592, 592, - 186, 186, 0, 0, 0, 475, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 898, 900, 0, 186, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1760, 1761, 0, 0, 0, 0, 475, 475, 475, 0, - 186, 0, 0, 0, 0, 1781, 1782, 0, 1783, 1784, - 0, 0, 0, 0, 0, 0, 1095, 0, 0, 1790, - 1791, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 184, 0, 0, 0, 184, 184, 184, 184, - 184, 0, 0, 0, 0, 0, 184, 184, 0, 0, - 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1022, 0, 1558, 1559, - 184, 0, 0, 0, 592, 0, 0, 0, 0, 0, - 1052, 0, 184, 0, 0, 184, 0, 0, 0, 0, - 1841, 0, 0, 0, 0, 0, 0, 0, 475, 475, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 475, 0, 0, 475, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 578, 578, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 475, 475, 475, - 186, 523, 32, 0, 0, 578, 0, 851, 0, 0, - 0, 475, 0, 475, 0, 1886, 0, 0, 0, 475, - 0, 184, 0, 0, 0, 0, 0, 0, 0, 1372, - 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 186, 0, 0, 0, 0, 0, 0, - 578, 184, 0, 0, 475, 186, 0, 0, 0, 0, - 0, 1149, 184, 184, 184, 184, 184, 0, 0, 0, - 0, 0, 0, 0, 1661, 0, 0, 556, 184, 0, - 0, 184, 184, 0, 0, 184, 1671, 1247, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 735, 0, - 0, 0, 0, 0, 0, 0, 475, 475, 0, 0, - 0, 1148, 0, 0, 0, 1154, 1154, 0, 1154, 0, - 1154, 1154, 0, 1163, 1154, 1154, 1154, 1154, 1154, 0, - 0, 0, 475, 0, 0, 0, 1148, 1148, 735, 0, - 475, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1028, 0, 0, 1039, 1972, 1973, 1974, 1975, - 1976, 1149, 0, 0, 1979, 1980, 0, 0, 0, 1223, - 0, 1247, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 184, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 184, 592, 592, 0, 592, 592, 0, - 592, 592, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 578, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 166, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1715, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 108, 0, 130, 0, 0, 0, - 0, 0, 0, 0, 150, 184, 0, 0, 0, 0, - 0, 0, 0, 0, 1324, 0, 592, 0, 1149, 0, - 0, 0, 0, 0, 1057, 0, 0, 0, 2079, 0, - 1148, 0, 0, 0, 0, 140, 1115, 0, 0, 0, - 129, 0, 0, 0, 184, 0, 0, 1356, 1357, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 147, 0, - 148, 0, 0, 0, 0, 1129, 1130, 139, 138, 165, - 1388, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1022, 0, 0, 592, 0, 0, 0, 0, 0, 0, - 0, 184, 184, 0, 0, 1185, 0, 0, 0, 1149, - 0, 592, 0, 0, 592, 0, 0, 0, 0, 184, - 0, 0, 0, 0, 0, 735, 0, 134, 1131, 141, - 0, 1128, 0, 135, 136, 0, 0, 151, 0, 0, - 1233, 184, 0, 0, 0, 0, 1039, 156, 0, 1244, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1252, 0, 1254, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1268, - 742, 0, 1271, 0, 0, 0, 0, 0, 0, 0, - 892, 892, 892, 0, 0, 0, 0, 0, 0, 0, - 0, 735, 0, 0, 0, 0, 1149, 742, 0, 0, - 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 941, 943, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, - 0, 735, 956, 0, 0, 0, 961, 962, 963, 964, - 965, 966, 967, 968, 0, 971, 974, 974, 974, 980, - 974, 974, 980, 974, 988, 989, 990, 991, 992, 993, - 994, 0, 0, 0, 0, 0, 0, 0, 32, 0, - 0, 166, 0, 0, 0, 0, 0, 137, 0, 0, - 0, 1372, 0, 0, 0, 0, 0, 0, 0, 131, - 0, 0, 132, 0, 1035, 0, 108, 0, 130, 0, - 1395, 0, 0, 0, 0, 0, 150, 1399, 0, 1402, - 0, 0, 0, 0, 0, 0, 0, 0, 1421, 0, - 0, 0, 0, 0, 184, 0, 0, 1565, 0, 0, - 0, 0, 0, 0, 0, 0, 184, 140, 0, 0, - 0, 0, 129, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 147, 0, 148, 0, 0, 0, 0, 117, 118, 139, - 138, 165, 0, 0, 0, 0, 0, 0, 0, 0, + 184, 184, 184, 184, 184, 0, 0, 0, 0, 0, + 184, 184, 0, 0, 184, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1024, 0, 1560, 1561, 184, 0, 0, 0, 593, 0, + 0, 0, 0, 0, 1054, 0, 184, 0, 0, 184, + 0, 0, 0, 1843, 0, 0, 0, 0, 0, 0, + 0, 475, 475, 0, 0, 0, 0, 0, 523, 32, + 0, 0, 0, 0, 475, 0, 0, 475, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1030, 0, 0, 1041, 0, 0, 579, 579, + 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, + 475, 475, 475, 186, 0, 0, 0, 0, 0, 579, + 0, 0, 0, 0, 475, 0, 475, 0, 1888, 0, + 0, 0, 475, 0, 0, 184, 0, 0, 0, 0, + 0, 0, 0, 1374, 557, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, + 0, 0, 0, 0, 579, 184, 0, 475, 186, 0, + 0, 0, 0, 0, 0, 1151, 184, 184, 184, 184, + 184, 0, 0, 0, 0, 0, 0, 0, 1663, 0, + 0, 0, 184, 0, 0, 184, 184, 0, 0, 184, + 1673, 1249, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 736, 0, 0, 0, 0, 0, 0, 475, + 475, 0, 0, 0, 0, 1150, 0, 0, 0, 1156, + 1156, 0, 1156, 0, 1156, 1156, 0, 1165, 1156, 1156, + 1156, 1156, 1156, 0, 1059, 475, 0, 0, 0, 0, + 1150, 1150, 736, 475, 0, 0, 1117, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1974, + 1975, 1976, 1977, 1978, 0, 1151, 0, 1981, 1982, 0, + 0, 0, 0, 1225, 0, 1249, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, + 0, 0, 0, 0, 0, 1187, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 184, 593, 593, + 0, 593, 593, 0, 593, 593, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1235, 0, 579, 0, 0, 0, 1041, 0, 0, 1246, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1254, 0, 1256, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1270, + 0, 0, 1273, 0, 0, 0, 0, 0, 0, 184, + 0, 0, 0, 0, 0, 0, 0, 0, 1326, 0, + 593, 0, 1151, 0, 0, 0, 0, 0, 0, 0, + 0, 2081, 0, 0, 1150, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, + 0, 0, 1358, 1359, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1024, 0, 0, 593, 166, + 0, 0, 0, 0, 0, 184, 184, 0, 0, 0, + 0, 0, 0, 1151, 0, 0, 593, 0, 0, 593, + 0, 0, 0, 184, 108, 0, 130, 0, 0, 0, + 736, 0, 0, 0, 150, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 184, 0, 893, 893, 893, + 0, 1397, 0, 0, 0, 0, 0, 0, 1401, 0, + 1404, 0, 0, 0, 0, 140, 0, 32, 0, 1423, + 129, 0, 0, 0, 0, 0, 0, 0, 942, 944, + 0, 0, 0, 0, 0, 743, 0, 0, 147, 0, + 148, 0, 0, 0, 0, 117, 118, 139, 138, 165, + 0, 0, 0, 0, 0, 0, 736, 0, 0, 957, + 1151, 0, 743, 962, 963, 964, 965, 966, 967, 968, + 969, 0, 972, 974, 977, 977, 977, 974, 977, 977, + 974, 977, 990, 991, 992, 993, 994, 995, 996, 0, + 0, 0, 0, 0, 0, 0, 32, 134, 115, 141, + 122, 114, 0, 135, 136, 0, 736, 151, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 156, 123, 0, + 0, 0, 1037, 0, 0, 0, 0, 0, 1081, 0, + 0, 0, 126, 124, 119, 120, 121, 125, 0, 0, + 0, 0, 116, 0, 0, 0, 0, 0, 917, 0, + 920, 127, 0, 0, 0, 1374, 934, 935, 936, 937, + 938, 939, 940, 0, 918, 919, 916, 922, 921, 931, + 932, 924, 925, 926, 927, 928, 929, 930, 923, 0, + 0, 933, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, + 0, 0, 1567, 0, 0, 0, 0, 1041, 0, 0, + 184, 1543, 1544, 1545, 1546, 1547, 0, 0, 143, 0, + 0, 1551, 1552, 0, 0, 1556, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1069, 0, 0, 0, 0, 1562, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1564, 0, 0, + 1566, 0, 0, 0, 0, 0, 0, 137, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, + 0, 0, 132, 1082, 0, 1151, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1150, 0, 1095, + 1098, 1099, 1100, 1101, 1102, 1103, 0, 1104, 1105, 1106, + 1107, 1108, 1083, 1084, 1085, 1086, 1067, 1068, 1096, 0, + 1070, 0, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, + 1079, 1080, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 0, 0, 144, 149, 146, 152, 153, 154, 155, 157, 158, 159, 160, 0, 0, 0, 0, 0, 161, 162, 163, 164, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1149, 0, 0, 0, 0, 0, 0, 0, 134, - 115, 141, 122, 114, 0, 135, 136, 0, 0, 151, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, - 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1148, 0, 126, 124, 119, 120, 121, 125, - 0, 0, 0, 0, 116, 0, 0, 0, 0, 0, - 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1670, 0, 0, + 1713, 0, 0, 0, 0, 893, 893, 0, 893, 893, + 0, 893, 893, 1719, 0, 0, 0, 1150, 0, 1726, + 1097, 0, 1719, 0, 0, 0, 0, 593, 0, 1731, + 33, 34, 35, 68, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 72, 0, 0, 0, 0, 39, 65, 66, 0, 63, + 0, 0, 0, 0, 0, 64, 0, 0, 593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1039, 0, 0, 0, - 1541, 1542, 1543, 1544, 1545, 0, 0, 0, 0, 0, - 1549, 1550, 0, 0, 1554, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1711, 0, 0, 0, 0, - 143, 0, 0, 0, 1560, 0, 0, 0, 1717, 0, - 0, 0, 1148, 0, 1724, 0, 1562, 1717, 0, 1564, - 0, 0, 592, 0, 1729, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 892, 892, 137, - 892, 892, 0, 892, 892, 0, 0, 0, 0, 0, - 0, 131, 0, 592, 132, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 52, 593, 0, 0, 0, 0, + 0, 0, 0, 0, 67, 0, 0, 0, 1743, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1757, 0, + 0, 1156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 592, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 593, 0, 0, 1150, 0, 0, 1817, 1156, 0, + 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 45, 48, 47, + 50, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1802, 0, 0, 0, 0, 0, 0, 51, 71, 70, + 0, 0, 60, 61, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1154, 0, 0, 0, + 0, 0, 736, 0, 0, 1150, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, + 0, 55, 56, 57, 58, 0, 0, 0, 0, 0, + 0, 0, 0, 1882, 1883, 1884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 592, 0, 0, 1148, - 0, 0, 1815, 1154, 144, 149, 146, 152, 153, 154, - 155, 157, 158, 159, 160, 0, 1668, 0, 0, 0, - 161, 162, 163, 164, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 166, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1125, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1420, 0, 108, - 0, 130, 0, 0, 0, 0, 0, 0, 0, 150, - 0, 0, 0, 0, 0, 0, 0, 735, 0, 0, - 1148, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1861, 1862, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 140, 0, 0, 0, 0, 129, 0, 0, 1880, 1881, - 1882, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 147, 0, 148, 0, 1741, 0, 0, - 1129, 1130, 139, 138, 165, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1755, 0, 0, + 0, 0, 0, 0, 1872, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1885, 0, 0, 0, + 0, 0, 1150, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1148, 0, 0, - 0, 0, 134, 1131, 141, 0, 1128, 0, 135, 136, - 0, 0, 151, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 156, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1800, - 1717, 1954, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1717, 0, 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1719, 1956, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1719, 0, + 0, 593, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1717, - 1717, 1717, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1996, 0, 1998, 0, 0, 0, 0, - 0, 1717, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 143, 0, 1859, 1860, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1870, 0, 0, 1717, 0, 0, 0, + 0, 0, 0, 0, 1719, 1719, 1719, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1998, 0, + 2000, 0, 0, 0, 0, 0, 1719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1883, 0, 0, 0, 0, - 0, 1580, 137, 0, 556, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 131, 0, 0, 132, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 592, 592, + 1582, 0, 0, 557, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1617, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1148, 0, 2076, 0, 0, 0, 0, 0, - 0, 0, 1717, 0, 0, 1035, 0, 0, 0, 0, - 0, 0, 1643, 1644, 0, 0, 1035, 1035, 1035, 1035, - 1035, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1420, 0, 0, 1035, 0, 0, 0, 1035, - 0, 0, 0, 0, 0, 0, 0, 144, 149, 146, - 152, 153, 154, 155, 157, 158, 159, 160, 0, 0, - 0, 0, 0, 161, 162, 163, 164, 0, 0, 0, + 0, 1719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1619, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1037, 0, 0, 0, 0, 2015, + 0, 1645, 1646, 593, 593, 1037, 1037, 1037, 1037, 1037, + 0, 2024, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1422, 0, 0, 1037, 0, 0, 1150, 1037, 2078, + 0, 0, 0, 0, 0, 0, 0, 1719, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1730, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2013, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2022, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 892, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 893, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1812, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1035, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1814, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1037, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1904, 0, 0, - 0, 0, 0, 0, 1910, 1911, 1912, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1906, 0, 0, 0, + 0, 0, 0, 1912, 1913, 1914, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1812, 0, 32, 0, 1812, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1812, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 713, 700, 32, 2052, 651, 716, 622, 640, 725, - 642, 645, 683, 603, 664, 321, 637, 0, 626, 599, - 633, 600, 624, 653, 237, 657, 621, 702, 667, 715, - 280, 0, 627, 334, 685, 370, 223, 289, 287, 396, - 246, 240, 236, 222, 265, 294, 332, 387, 326, 722, - 284, 674, 0, 379, 306, 0, 0, 0, 655, 705, - 662, 696, 650, 684, 611, 673, 717, 638, 681, 718, - 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, - 175, 176, 0, 2059, 2060, 0, 0, 0, 0, 0, - 213, 0, 219, 678, 712, 635, 680, 233, 268, 239, - 232, 394, 682, 728, 598, 675, 0, 601, 604, 724, - 708, 630, 631, 0, 0, 0, 0, 0, 0, 0, - 654, 663, 693, 648, 0, 0, 0, 0, 0, 0, - 0, 0, 628, 0, 672, 0, 0, 0, 607, 602, - 0, 0, 0, 0, 652, 0, 0, 0, 610, 0, - 629, 694, 0, 596, 256, 605, 307, 698, 707, 649, - 421, 711, 647, 646, 714, 689, 608, 704, 641, 279, - 606, 276, 188, 202, 0, 639, 317, 355, 360, 703, - 625, 634, 224, 632, 358, 330, 409, 209, 247, 352, - 335, 356, 671, 687, 357, 285, 398, 347, 408, 422, - 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, - 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, - 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, - 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, - 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, - 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, - 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, - 193, 0, 381, 413, 434, 211, 620, 699, 393, 427, - 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, - 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 691, 727, 329, 359, 215, 411, 378, 615, 619, - 613, 614, 665, 666, 616, 719, 720, 721, 695, 609, - 0, 617, 618, 0, 701, 709, 710, 670, 187, 200, - 282, 723, 349, 250, 432, 416, 414, 597, 612, 230, - 623, 0, 0, 636, 643, 644, 656, 658, 659, 660, - 661, 669, 676, 677, 679, 686, 688, 690, 692, 697, - 706, 726, 189, 190, 201, 208, 217, 229, 242, 248, - 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, - 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, - 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, - 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, - 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, - 425, 0, 290, 668, 194, 220, 207, 227, 241, 243, - 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 713, 700, 0, - 0, 651, 716, 622, 640, 725, 642, 645, 683, 603, - 664, 321, 637, 0, 626, 599, 633, 600, 624, 653, - 237, 657, 621, 702, 667, 715, 280, 0, 627, 334, - 685, 370, 223, 289, 287, 396, 246, 240, 236, 222, - 265, 294, 332, 387, 326, 722, 284, 674, 0, 379, - 306, 0, 0, 0, 655, 705, 662, 696, 650, 684, - 611, 673, 717, 638, 681, 718, 270, 221, 192, 318, - 380, 249, 0, 0, 0, 174, 175, 176, 0, 0, - 0, 0, 0, 0, 0, 0, 213, 0, 219, 678, - 712, 635, 680, 233, 268, 239, 232, 394, 682, 728, - 598, 675, 0, 601, 604, 724, 708, 630, 631, 0, - 0, 0, 0, 0, 0, 0, 654, 663, 693, 648, - 0, 0, 0, 0, 0, 0, 1804, 0, 628, 0, - 672, 0, 0, 0, 607, 602, 0, 0, 0, 0, - 652, 0, 0, 0, 610, 0, 629, 694, 0, 596, - 256, 605, 307, 698, 707, 649, 421, 711, 647, 646, - 714, 689, 608, 704, 641, 279, 606, 276, 188, 202, - 0, 639, 317, 355, 360, 703, 625, 634, 224, 632, - 358, 330, 409, 209, 247, 352, 335, 356, 671, 687, - 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, - 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, - 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, - 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, - 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, - 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, - 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, - 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, - 434, 211, 620, 699, 393, 427, 430, 0, 348, 212, - 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, - 259, 312, 206, 264, 377, 277, 286, 691, 727, 329, - 359, 215, 411, 378, 615, 619, 613, 614, 665, 666, - 616, 719, 720, 721, 695, 609, 0, 617, 618, 0, - 701, 709, 710, 670, 187, 200, 282, 723, 349, 250, - 432, 416, 414, 597, 612, 230, 623, 0, 0, 636, - 643, 644, 656, 658, 659, 660, 661, 669, 676, 677, - 679, 686, 688, 690, 692, 697, 706, 726, 189, 190, - 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, - 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, - 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, - 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, - 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, - 400, 410, 420, 424, 258, 407, 425, 0, 290, 668, - 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, - 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, - 392, 303, 234, 713, 700, 0, 0, 651, 716, 622, - 640, 725, 642, 645, 683, 603, 664, 321, 637, 0, - 626, 599, 633, 600, 624, 653, 237, 657, 621, 702, - 667, 715, 280, 0, 627, 334, 685, 370, 223, 289, - 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, - 326, 722, 284, 674, 0, 379, 306, 0, 0, 0, - 655, 705, 662, 696, 650, 684, 611, 673, 717, 638, - 681, 718, 270, 221, 192, 318, 380, 249, 67, 0, - 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, - 0, 0, 213, 0, 219, 678, 712, 635, 680, 233, - 268, 239, 232, 394, 682, 728, 598, 675, 0, 601, - 604, 724, 708, 630, 631, 0, 0, 0, 0, 0, - 0, 0, 654, 663, 693, 648, 0, 0, 0, 0, - 0, 0, 0, 0, 628, 0, 672, 0, 0, 0, - 607, 602, 0, 0, 0, 0, 652, 0, 0, 0, - 610, 0, 629, 694, 0, 596, 256, 605, 307, 698, - 707, 649, 421, 711, 647, 646, 714, 689, 608, 704, - 641, 279, 606, 276, 188, 202, 0, 639, 317, 355, - 360, 703, 625, 634, 224, 632, 358, 330, 409, 209, - 247, 352, 335, 356, 671, 687, 357, 285, 398, 347, - 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, - 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, - 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, - 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, - 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, - 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, - 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, - 310, 0, 193, 0, 381, 413, 434, 211, 620, 699, - 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, - 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, - 377, 277, 286, 691, 727, 329, 359, 215, 411, 378, - 615, 619, 613, 614, 665, 666, 616, 719, 720, 721, - 695, 609, 0, 617, 618, 0, 701, 709, 710, 670, - 187, 200, 282, 723, 349, 250, 432, 416, 414, 597, - 612, 230, 623, 0, 0, 636, 643, 644, 656, 658, - 659, 660, 661, 669, 676, 677, 679, 686, 688, 690, - 692, 697, 706, 726, 189, 190, 201, 208, 217, 229, - 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, - 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, - 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, - 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, - 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, - 258, 407, 425, 0, 290, 668, 194, 220, 207, 227, - 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, - 353, 216, 369, 388, 389, 390, 392, 303, 234, 713, - 700, 0, 0, 651, 716, 622, 640, 725, 642, 645, - 683, 603, 664, 321, 637, 0, 626, 599, 633, 600, - 624, 653, 237, 657, 621, 702, 667, 715, 280, 0, - 627, 334, 685, 370, 223, 289, 287, 396, 246, 240, - 236, 222, 265, 294, 332, 387, 326, 722, 284, 674, - 0, 379, 306, 0, 0, 0, 655, 705, 662, 696, - 650, 684, 611, 673, 717, 638, 681, 718, 270, 221, - 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, - 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, - 219, 678, 712, 635, 680, 233, 268, 239, 232, 394, - 682, 728, 598, 675, 0, 601, 604, 724, 708, 630, - 631, 0, 0, 0, 0, 0, 0, 0, 654, 663, - 693, 648, 0, 0, 0, 0, 0, 0, 1672, 0, - 628, 0, 672, 0, 0, 0, 607, 602, 0, 0, - 0, 0, 652, 0, 0, 0, 610, 0, 629, 694, - 0, 596, 256, 605, 307, 698, 707, 649, 421, 711, - 647, 646, 714, 689, 608, 704, 641, 279, 606, 276, - 188, 202, 0, 639, 317, 355, 360, 703, 625, 634, - 224, 632, 358, 330, 409, 209, 247, 352, 335, 356, - 671, 687, 357, 285, 398, 347, 408, 422, 423, 231, - 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, - 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, - 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, - 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, - 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, - 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, - 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, - 381, 413, 434, 211, 620, 699, 393, 427, 430, 0, - 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, - 210, 342, 259, 312, 206, 264, 377, 277, 286, 691, - 727, 329, 359, 215, 411, 378, 615, 619, 613, 614, - 665, 666, 616, 719, 720, 721, 695, 609, 0, 617, - 618, 0, 701, 709, 710, 670, 187, 200, 282, 723, - 349, 250, 432, 416, 414, 597, 612, 230, 623, 0, - 0, 636, 643, 644, 656, 658, 659, 660, 661, 669, - 676, 677, 679, 686, 688, 690, 692, 697, 706, 726, - 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, - 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, - 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, - 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, - 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, - 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, - 290, 668, 194, 220, 207, 227, 241, 243, 271, 299, - 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, - 389, 390, 392, 303, 234, 713, 700, 0, 0, 651, - 716, 622, 640, 725, 642, 645, 683, 603, 664, 321, - 637, 0, 626, 599, 633, 600, 624, 653, 237, 657, - 621, 702, 667, 715, 280, 0, 627, 334, 685, 370, - 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, - 332, 387, 326, 722, 284, 674, 0, 379, 306, 0, - 0, 0, 655, 705, 662, 696, 650, 684, 611, 673, - 717, 638, 681, 718, 270, 221, 192, 318, 380, 249, - 0, 0, 0, 174, 175, 176, 0, 0, 0, 0, - 0, 0, 0, 0, 213, 0, 219, 678, 712, 635, - 680, 233, 268, 239, 232, 394, 682, 728, 598, 675, - 0, 601, 604, 724, 708, 630, 631, 0, 0, 0, - 0, 0, 0, 0, 654, 663, 693, 648, 0, 0, - 0, 0, 0, 0, 1397, 0, 628, 0, 672, 0, - 0, 0, 607, 602, 0, 0, 0, 0, 652, 0, - 0, 0, 610, 0, 629, 694, 0, 596, 256, 605, - 307, 698, 707, 649, 421, 711, 647, 646, 714, 689, - 608, 704, 641, 279, 606, 276, 188, 202, 0, 639, - 317, 355, 360, 703, 625, 634, 224, 632, 358, 330, - 409, 209, 247, 352, 335, 356, 671, 687, 357, 285, - 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, - 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, - 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, - 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, - 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, - 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, - 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, - 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, - 620, 699, 393, 427, 430, 0, 348, 212, 253, 244, - 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, - 206, 264, 377, 277, 286, 691, 727, 329, 359, 215, - 411, 378, 615, 619, 613, 614, 665, 666, 616, 719, - 720, 721, 695, 609, 0, 617, 618, 0, 701, 709, - 710, 670, 187, 200, 282, 723, 349, 250, 432, 416, - 414, 597, 612, 230, 623, 0, 0, 636, 643, 644, - 656, 658, 659, 660, 661, 669, 676, 677, 679, 686, - 688, 690, 692, 697, 706, 726, 189, 190, 201, 208, - 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, - 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, - 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, - 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, - 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, - 420, 424, 258, 407, 425, 0, 290, 668, 194, 220, - 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, - 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, - 234, 713, 700, 0, 0, 651, 716, 622, 640, 725, - 642, 645, 683, 603, 664, 321, 637, 0, 626, 599, - 633, 600, 624, 653, 237, 657, 621, 702, 667, 715, - 280, 0, 627, 334, 685, 370, 223, 289, 287, 396, - 246, 240, 236, 222, 265, 294, 332, 387, 326, 722, - 284, 674, 0, 379, 306, 0, 0, 0, 655, 705, - 662, 696, 650, 684, 611, 673, 717, 638, 681, 718, - 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, - 175, 176, 0, 0, 0, 0, 0, 0, 0, 0, - 213, 0, 219, 678, 712, 635, 680, 233, 268, 239, - 232, 394, 682, 728, 598, 675, 0, 601, 604, 724, - 708, 630, 631, 0, 0, 0, 0, 0, 0, 0, - 654, 663, 693, 648, 0, 0, 0, 0, 0, 0, - 0, 0, 628, 0, 672, 0, 0, 0, 607, 602, - 0, 0, 0, 0, 652, 0, 0, 0, 610, 0, - 629, 694, 0, 596, 256, 605, 307, 698, 707, 649, - 421, 711, 647, 646, 714, 689, 608, 704, 641, 279, - 606, 276, 188, 202, 0, 639, 317, 355, 360, 703, - 625, 634, 224, 632, 358, 330, 409, 209, 247, 352, - 335, 356, 671, 687, 357, 285, 398, 347, 408, 422, - 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, - 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, - 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, - 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, - 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, - 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, - 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, - 193, 0, 381, 413, 434, 211, 620, 699, 393, 427, - 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, - 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 691, 727, 329, 359, 215, 411, 378, 615, 619, - 613, 614, 665, 666, 616, 719, 720, 721, 695, 609, - 0, 617, 618, 0, 701, 709, 710, 670, 187, 200, - 282, 723, 349, 250, 432, 416, 414, 597, 612, 230, - 623, 0, 0, 636, 643, 644, 656, 658, 659, 660, - 661, 669, 676, 677, 679, 686, 688, 690, 692, 697, - 706, 726, 189, 190, 201, 208, 217, 229, 242, 248, - 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, - 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, - 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, - 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, - 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, - 425, 0, 290, 668, 194, 220, 207, 227, 241, 243, - 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 713, 700, 0, - 0, 651, 716, 622, 640, 725, 642, 645, 683, 603, - 664, 321, 637, 0, 626, 599, 633, 600, 624, 653, - 237, 657, 621, 702, 667, 715, 280, 0, 627, 334, - 685, 370, 223, 289, 287, 396, 246, 240, 236, 222, - 265, 294, 332, 387, 326, 722, 284, 674, 0, 379, - 306, 0, 0, 0, 655, 705, 662, 696, 650, 684, - 611, 673, 717, 638, 681, 718, 270, 221, 192, 318, - 380, 249, 0, 0, 0, 174, 175, 176, 0, 0, - 0, 0, 0, 0, 0, 0, 213, 0, 219, 678, - 712, 635, 680, 233, 268, 239, 232, 394, 682, 728, - 598, 675, 0, 601, 604, 724, 708, 630, 631, 0, - 0, 0, 0, 0, 0, 0, 654, 663, 693, 648, - 0, 0, 0, 0, 0, 0, 0, 0, 628, 0, - 672, 0, 0, 0, 607, 602, 0, 0, 0, 0, - 652, 0, 0, 0, 610, 0, 629, 694, 0, 596, - 256, 605, 307, 698, 707, 649, 421, 711, 647, 646, - 714, 689, 608, 704, 641, 279, 606, 276, 188, 202, - 0, 639, 317, 355, 360, 703, 625, 634, 224, 632, - 358, 330, 409, 209, 247, 352, 335, 356, 671, 687, - 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, - 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, - 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, - 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, - 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, - 433, 204, 418, 199, 730, 417, 313, 397, 405, 302, - 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, - 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, - 434, 211, 620, 699, 393, 427, 430, 0, 348, 212, - 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, - 259, 595, 729, 589, 588, 277, 286, 691, 727, 329, - 359, 215, 411, 378, 615, 619, 613, 614, 665, 666, - 616, 719, 720, 721, 695, 609, 0, 617, 618, 0, - 701, 709, 710, 670, 187, 200, 282, 723, 349, 250, - 432, 416, 414, 597, 612, 230, 623, 0, 0, 636, - 643, 644, 656, 658, 659, 660, 661, 669, 676, 677, - 679, 686, 688, 690, 692, 697, 706, 726, 189, 190, - 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, - 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, - 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, - 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, - 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, - 400, 410, 420, 424, 258, 407, 425, 0, 290, 668, - 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, - 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, - 392, 303, 234, 713, 700, 0, 0, 651, 716, 622, - 640, 725, 642, 645, 683, 603, 664, 321, 637, 0, - 626, 599, 633, 600, 624, 653, 237, 657, 621, 702, - 667, 715, 280, 0, 627, 334, 685, 370, 223, 289, - 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, - 326, 722, 284, 674, 0, 379, 306, 0, 0, 0, - 655, 705, 662, 696, 650, 684, 611, 673, 717, 638, - 681, 718, 270, 221, 192, 318, 380, 249, 0, 0, - 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, - 0, 0, 213, 0, 219, 678, 712, 635, 680, 233, - 268, 239, 232, 394, 682, 728, 598, 675, 0, 601, - 604, 724, 708, 630, 631, 0, 0, 0, 0, 0, - 0, 0, 654, 663, 693, 648, 0, 0, 0, 0, - 0, 0, 0, 0, 628, 0, 672, 0, 0, 0, - 607, 602, 0, 0, 0, 0, 652, 0, 0, 0, - 610, 0, 629, 694, 0, 596, 256, 605, 307, 698, - 707, 649, 421, 711, 647, 646, 714, 689, 608, 704, - 641, 279, 606, 276, 188, 202, 0, 639, 317, 355, - 360, 703, 625, 634, 224, 632, 358, 330, 409, 209, - 247, 352, 335, 356, 671, 687, 357, 285, 398, 347, - 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, - 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, - 191, 283, 195, 386, 1043, 214, 368, 0, 0, 0, - 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, - 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, - 730, 417, 313, 397, 405, 302, 293, 198, 403, 300, - 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, - 310, 0, 193, 0, 381, 413, 434, 211, 620, 699, - 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, - 281, 426, 428, 429, 210, 342, 259, 595, 729, 589, - 588, 277, 286, 691, 727, 329, 359, 215, 411, 378, - 615, 619, 613, 614, 665, 666, 616, 719, 720, 721, - 695, 609, 0, 617, 618, 0, 701, 709, 710, 670, - 187, 200, 282, 723, 349, 250, 432, 416, 414, 597, - 612, 230, 623, 0, 0, 636, 643, 644, 656, 658, - 659, 660, 661, 669, 676, 677, 679, 686, 688, 690, - 692, 697, 706, 726, 189, 190, 201, 208, 217, 229, - 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, - 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, - 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, - 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, - 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, - 258, 407, 425, 0, 290, 668, 194, 220, 207, 227, - 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, - 353, 216, 369, 388, 389, 390, 392, 303, 234, 713, - 700, 0, 0, 651, 716, 622, 640, 725, 642, 645, - 683, 603, 664, 321, 637, 0, 626, 599, 633, 600, - 624, 653, 237, 657, 621, 702, 667, 715, 280, 0, - 627, 334, 685, 370, 223, 289, 287, 396, 246, 240, - 236, 222, 265, 294, 332, 387, 326, 722, 284, 674, - 0, 379, 306, 0, 0, 0, 655, 705, 662, 696, - 650, 684, 611, 673, 717, 638, 681, 718, 270, 221, - 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, - 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, - 219, 678, 712, 635, 680, 233, 268, 239, 232, 394, - 682, 728, 598, 675, 0, 601, 604, 724, 708, 630, - 631, 0, 0, 0, 0, 0, 0, 0, 654, 663, - 693, 648, 0, 0, 0, 0, 0, 0, 0, 0, - 628, 0, 672, 0, 0, 0, 607, 602, 0, 0, - 0, 0, 652, 0, 0, 0, 610, 0, 629, 694, - 0, 596, 256, 605, 307, 698, 707, 649, 421, 711, - 647, 646, 714, 689, 608, 704, 641, 279, 606, 276, - 188, 202, 0, 639, 317, 355, 360, 703, 625, 634, - 224, 632, 358, 330, 409, 209, 247, 352, 335, 356, - 671, 687, 357, 285, 398, 347, 408, 422, 423, 231, - 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, - 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, - 586, 214, 368, 0, 0, 0, 197, 404, 383, 301, - 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, - 402, 225, 433, 204, 418, 199, 730, 417, 313, 397, - 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, - 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, - 381, 413, 434, 211, 620, 699, 393, 427, 430, 0, - 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, - 210, 342, 259, 595, 729, 589, 588, 277, 286, 691, - 727, 329, 359, 215, 411, 378, 615, 619, 613, 614, - 665, 666, 616, 719, 720, 721, 695, 609, 0, 617, - 618, 0, 701, 709, 710, 670, 187, 200, 282, 723, - 349, 250, 432, 416, 414, 597, 612, 230, 623, 0, - 0, 636, 643, 644, 656, 658, 659, 660, 661, 669, - 676, 677, 679, 686, 688, 690, 692, 697, 706, 726, - 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, - 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, - 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, - 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, - 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, - 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, - 290, 668, 194, 220, 207, 227, 241, 243, 271, 299, - 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, - 389, 390, 392, 303, 234, 321, 0, 0, 1326, 0, - 490, 0, 0, 0, 237, 0, 489, 0, 0, 0, - 280, 0, 1327, 334, 0, 370, 223, 289, 287, 396, - 246, 240, 236, 222, 265, 294, 332, 387, 326, 533, - 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, - 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, - 270, 221, 192, 318, 380, 249, 67, 0, 0, 174, - 175, 176, 511, 510, 513, 514, 515, 516, 0, 0, - 213, 512, 219, 517, 518, 519, 0, 233, 268, 239, - 232, 394, 0, 0, 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 501, 502, - 576, 0, 0, 0, 547, 0, 503, 0, 0, 496, - 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 256, 0, 307, 546, 0, 0, - 421, 0, 0, 544, 0, 0, 0, 0, 0, 279, - 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, - 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, - 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, - 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, - 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, - 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, - 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, - 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, - 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, - 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, - 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, - 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, - 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 0, 0, 329, 359, 215, 411, 378, 534, 545, - 540, 541, 538, 539, 0, 537, 536, 535, 548, 526, - 527, 528, 529, 531, 0, 542, 543, 530, 187, 200, - 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, + 0, 0, 1814, 0, 32, 0, 1814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, - 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, - 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, - 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, - 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, - 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, - 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, - 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 321, 0, 0, - 0, 0, 490, 0, 0, 0, 237, 0, 489, 0, - 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, - 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, - 326, 533, 284, 0, 0, 379, 306, 0, 0, 0, - 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, - 1436, 0, 270, 221, 192, 318, 380, 249, 67, 0, - 0, 174, 175, 176, 511, 510, 513, 514, 515, 516, - 0, 0, 213, 512, 219, 517, 518, 519, 1437, 233, - 268, 239, 232, 394, 0, 0, 0, 487, 504, 0, - 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 501, 502, 0, 0, 0, 0, 547, 0, 503, 0, - 0, 496, 497, 499, 498, 500, 505, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 256, 0, 307, 546, - 0, 0, 421, 0, 0, 544, 0, 0, 0, 0, - 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, - 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, - 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, - 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, - 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, - 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, - 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, - 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, - 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, - 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, - 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, - 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, - 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, - 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, - 534, 545, 540, 541, 538, 539, 0, 537, 536, 535, - 548, 526, 527, 528, 529, 531, 0, 542, 543, 530, - 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, - 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, - 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, - 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, - 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, - 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, - 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, - 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, - 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, - 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, - 0, 0, 0, 0, 490, 0, 0, 0, 237, 0, - 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, - 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, - 332, 387, 326, 533, 284, 0, 0, 379, 306, 0, - 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, - 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, - 67, 0, 564, 174, 175, 176, 511, 510, 513, 514, - 515, 516, 0, 0, 213, 512, 219, 517, 518, 519, - 0, 233, 268, 239, 232, 394, 0, 0, 0, 487, - 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 501, 502, 0, 0, 0, 0, 547, 0, - 503, 0, 0, 496, 497, 499, 498, 500, 505, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, - 307, 546, 0, 0, 421, 0, 0, 544, 0, 0, - 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, - 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, - 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, - 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, - 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, - 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, - 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, - 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, - 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, - 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, - 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, - 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, - 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, - 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, - 411, 378, 534, 545, 540, 541, 538, 539, 0, 537, - 536, 535, 548, 526, 527, 528, 529, 531, 0, 542, - 543, 530, 187, 200, 282, 0, 349, 250, 432, 416, - 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1814, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, - 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, - 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, - 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, - 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, - 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, - 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, - 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, - 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, - 234, 321, 0, 0, 0, 0, 490, 0, 0, 0, - 237, 0, 489, 0, 0, 0, 280, 0, 0, 334, - 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, - 265, 294, 332, 387, 326, 533, 284, 0, 0, 379, - 306, 0, 0, 0, 0, 0, 524, 525, 0, 0, - 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, - 380, 249, 67, 0, 0, 174, 175, 176, 511, 510, - 513, 514, 515, 516, 0, 0, 213, 512, 219, 517, - 518, 519, 0, 233, 268, 239, 232, 394, 0, 0, - 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 501, 502, 576, 0, 0, 0, - 547, 0, 503, 0, 0, 496, 497, 499, 498, 500, - 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 256, 0, 307, 546, 0, 0, 421, 0, 0, 544, - 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, - 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, - 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, - 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, - 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, - 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, - 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, - 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, - 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, - 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, - 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, - 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, - 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, - 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, - 359, 215, 411, 378, 534, 545, 540, 541, 538, 539, - 0, 537, 536, 535, 548, 526, 527, 528, 529, 531, - 0, 542, 543, 530, 187, 200, 282, 0, 349, 250, - 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, - 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, - 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, - 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, - 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, - 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, - 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, - 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, - 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, - 392, 303, 234, 321, 0, 0, 0, 0, 490, 0, - 0, 0, 237, 0, 489, 0, 0, 0, 280, 0, - 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, - 236, 222, 265, 294, 332, 387, 326, 533, 284, 0, - 0, 379, 306, 0, 0, 0, 0, 0, 524, 525, - 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, - 192, 318, 380, 249, 67, 0, 0, 174, 175, 176, - 511, 1344, 513, 514, 515, 516, 0, 0, 213, 512, - 219, 517, 518, 519, 0, 233, 268, 239, 232, 394, - 0, 0, 0, 487, 504, 0, 532, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 501, 502, 576, 0, - 0, 0, 547, 0, 503, 0, 0, 496, 497, 499, - 498, 500, 505, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 256, 0, 307, 546, 0, 0, 421, 0, - 0, 544, 0, 0, 0, 0, 0, 279, 0, 276, - 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, - 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, - 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, - 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, - 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, - 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, - 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, - 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, - 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, - 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, - 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, - 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, - 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, - 0, 329, 359, 215, 411, 378, 534, 545, 540, 541, - 538, 539, 0, 537, 536, 535, 548, 526, 527, 528, - 529, 531, 0, 542, 543, 530, 187, 200, 282, 0, - 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, - 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, - 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, - 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, - 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, - 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, - 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, - 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, - 389, 390, 392, 303, 234, 321, 0, 0, 0, 0, - 490, 0, 0, 0, 237, 0, 489, 0, 0, 0, - 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, - 246, 240, 236, 222, 265, 294, 332, 387, 326, 533, - 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, - 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, - 270, 221, 192, 318, 380, 249, 67, 0, 0, 174, - 175, 176, 511, 1341, 513, 514, 515, 516, 0, 0, - 213, 512, 219, 517, 518, 519, 0, 233, 268, 239, - 232, 394, 0, 0, 0, 487, 504, 0, 532, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 501, 502, - 576, 0, 0, 0, 547, 0, 503, 0, 0, 496, - 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 256, 0, 307, 546, 0, 0, - 421, 0, 0, 544, 0, 0, 0, 0, 0, 279, - 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, - 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, - 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, - 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, - 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, - 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, - 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, - 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, - 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, - 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, - 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, - 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, - 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 0, 0, 329, 359, 215, 411, 378, 534, 545, - 540, 541, 538, 539, 0, 537, 536, 535, 548, 526, - 527, 528, 529, 531, 0, 542, 543, 530, 187, 200, - 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, - 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, - 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, - 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, - 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, - 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, - 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, - 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 557, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 321, 0, 0, 0, 0, 490, 0, 0, 0, 237, - 0, 489, 0, 0, 0, 280, 0, 0, 334, 0, + 714, 701, 32, 2054, 652, 717, 623, 641, 726, 643, + 646, 684, 604, 665, 321, 638, 0, 627, 600, 634, + 601, 625, 654, 237, 658, 622, 703, 668, 716, 280, + 0, 628, 334, 686, 370, 223, 289, 287, 396, 246, + 240, 236, 222, 265, 294, 332, 387, 326, 723, 284, + 675, 0, 379, 306, 0, 0, 0, 656, 706, 663, + 697, 651, 685, 612, 674, 718, 639, 682, 719, 270, + 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, + 176, 0, 2061, 2062, 0, 0, 0, 0, 0, 213, + 0, 219, 679, 713, 636, 681, 233, 268, 239, 232, + 394, 683, 729, 599, 676, 0, 602, 605, 725, 709, + 631, 632, 0, 0, 0, 0, 0, 0, 0, 655, + 664, 694, 649, 0, 0, 0, 0, 0, 0, 0, + 0, 629, 0, 673, 0, 0, 0, 608, 603, 0, + 0, 0, 0, 653, 0, 0, 0, 611, 0, 630, + 695, 0, 597, 256, 606, 307, 699, 708, 650, 421, + 712, 648, 647, 715, 690, 609, 705, 642, 279, 607, + 276, 188, 202, 0, 640, 317, 355, 360, 704, 626, + 635, 224, 633, 358, 330, 409, 209, 247, 352, 335, + 356, 672, 688, 357, 285, 398, 347, 408, 422, 423, + 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, + 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, + 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, + 301, 272, 273, 196, 0, 351, 235, 252, 226, 320, + 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, + 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, + 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, + 0, 381, 413, 434, 211, 621, 700, 393, 427, 430, + 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, + 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, + 692, 728, 329, 359, 215, 411, 378, 616, 620, 614, + 615, 666, 667, 617, 720, 721, 722, 696, 610, 0, + 618, 619, 0, 702, 710, 711, 671, 187, 200, 282, + 724, 349, 250, 432, 416, 414, 598, 613, 230, 624, + 0, 0, 637, 644, 645, 657, 659, 660, 661, 662, + 670, 677, 678, 680, 687, 689, 691, 693, 698, 707, + 727, 189, 190, 201, 208, 217, 229, 242, 248, 257, + 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, + 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, + 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, + 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, + 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, + 0, 290, 669, 194, 220, 207, 227, 241, 243, 271, + 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, + 388, 389, 390, 392, 303, 234, 714, 701, 0, 0, + 652, 717, 623, 641, 726, 643, 646, 684, 604, 665, + 321, 638, 0, 627, 600, 634, 601, 625, 654, 237, + 658, 622, 703, 668, 716, 280, 0, 628, 334, 686, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 533, 284, 0, 0, 379, 306, - 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 67, 0, 0, 174, 175, 176, 511, 510, 513, - 514, 515, 516, 0, 0, 213, 512, 219, 517, 518, - 519, 0, 233, 268, 239, 232, 394, 0, 0, 0, - 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 501, 502, 0, 0, 0, 0, 547, - 0, 503, 0, 0, 496, 497, 499, 498, 500, 505, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, - 0, 307, 546, 0, 0, 421, 0, 0, 544, 0, - 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, - 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, - 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, + 294, 332, 387, 326, 723, 284, 675, 0, 379, 306, + 0, 0, 0, 656, 706, 663, 697, 651, 685, 612, + 674, 718, 639, 682, 719, 270, 221, 192, 318, 380, + 249, 0, 0, 0, 174, 175, 176, 0, 0, 0, + 0, 0, 0, 0, 0, 213, 0, 219, 679, 713, + 636, 681, 233, 268, 239, 232, 394, 683, 729, 599, + 676, 0, 602, 605, 725, 709, 631, 632, 0, 0, + 0, 0, 0, 0, 0, 655, 664, 694, 649, 0, + 0, 0, 0, 0, 0, 1806, 0, 629, 0, 673, + 0, 0, 0, 608, 603, 0, 0, 0, 0, 653, + 0, 0, 0, 611, 0, 630, 695, 0, 597, 256, + 606, 307, 699, 708, 650, 421, 712, 648, 647, 715, + 690, 609, 705, 642, 279, 607, 276, 188, 202, 0, + 640, 317, 355, 360, 704, 626, 635, 224, 633, 358, + 330, 409, 209, 247, 352, 335, 356, 672, 688, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, @@ -2337,42 +1717,88 @@ var yyAct = [...]int{ 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, - 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, + 211, 621, 700, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, - 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, - 215, 411, 378, 534, 545, 540, 541, 538, 539, 0, - 537, 536, 535, 548, 526, 527, 528, 529, 531, 0, - 542, 543, 530, 187, 200, 282, 0, 349, 250, 432, - 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, + 312, 206, 264, 377, 277, 286, 692, 728, 329, 359, + 215, 411, 378, 616, 620, 614, 615, 666, 667, 617, + 720, 721, 722, 696, 610, 0, 618, 619, 0, 702, + 710, 711, 671, 187, 200, 282, 724, 349, 250, 432, + 416, 414, 598, 613, 230, 624, 0, 0, 637, 644, + 645, 657, 659, 660, 661, 662, 670, 677, 678, 680, + 687, 689, 691, 693, 698, 707, 727, 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, - 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, + 410, 420, 424, 258, 407, 425, 0, 290, 669, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, - 303, 234, 321, 0, 0, 0, 0, 490, 0, 0, - 0, 237, 0, 489, 0, 0, 0, 280, 0, 0, - 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, - 222, 265, 294, 332, 387, 326, 533, 284, 0, 0, - 379, 306, 0, 0, 0, 0, 0, 524, 525, 0, - 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, - 318, 380, 249, 67, 0, 0, 174, 175, 176, 511, - 510, 513, 514, 515, 516, 0, 0, 213, 512, 219, - 517, 518, 519, 0, 233, 268, 239, 232, 394, 0, - 0, 0, 487, 504, 0, 532, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 501, 502, 0, 0, 0, - 0, 547, 0, 503, 0, 0, 496, 497, 499, 498, - 500, 505, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 256, 0, 307, 546, 0, 0, 421, 0, 0, - 544, 0, 0, 0, 0, 0, 279, 0, 276, 188, - 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, - 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, - 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, + 303, 234, 714, 701, 0, 0, 652, 717, 623, 641, + 726, 643, 646, 684, 604, 665, 321, 638, 0, 627, + 600, 634, 601, 625, 654, 237, 658, 622, 703, 668, + 716, 280, 0, 628, 334, 686, 370, 223, 289, 287, + 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, + 723, 284, 675, 0, 379, 306, 0, 0, 0, 656, + 706, 663, 697, 651, 685, 612, 674, 718, 639, 682, + 719, 270, 221, 192, 318, 380, 249, 67, 0, 0, + 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, + 0, 213, 0, 219, 679, 713, 636, 681, 233, 268, + 239, 232, 394, 683, 729, 599, 676, 0, 602, 605, + 725, 709, 631, 632, 0, 0, 0, 0, 0, 0, + 0, 655, 664, 694, 649, 0, 0, 0, 0, 0, + 0, 0, 0, 629, 0, 673, 0, 0, 0, 608, + 603, 0, 0, 0, 0, 653, 0, 0, 0, 611, + 0, 630, 695, 0, 597, 256, 606, 307, 699, 708, + 650, 421, 712, 648, 647, 715, 690, 609, 705, 642, + 279, 607, 276, 188, 202, 0, 640, 317, 355, 360, + 704, 626, 635, 224, 633, 358, 330, 409, 209, 247, + 352, 335, 356, 672, 688, 357, 285, 398, 347, 408, + 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, + 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, + 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, + 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, + 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, + 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, + 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, + 0, 193, 0, 381, 413, 434, 211, 621, 700, 393, + 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, + 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, + 277, 286, 692, 728, 329, 359, 215, 411, 378, 616, + 620, 614, 615, 666, 667, 617, 720, 721, 722, 696, + 610, 0, 618, 619, 0, 702, 710, 711, 671, 187, + 200, 282, 724, 349, 250, 432, 416, 414, 598, 613, + 230, 624, 0, 0, 637, 644, 645, 657, 659, 660, + 661, 662, 670, 677, 678, 680, 687, 689, 691, 693, + 698, 707, 727, 189, 190, 201, 208, 217, 229, 242, + 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, + 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, + 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, + 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, + 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, + 407, 425, 0, 290, 669, 194, 220, 207, 227, 241, + 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, + 216, 369, 388, 389, 390, 392, 303, 234, 714, 701, + 0, 0, 652, 717, 623, 641, 726, 643, 646, 684, + 604, 665, 321, 638, 0, 627, 600, 634, 601, 625, + 654, 237, 658, 622, 703, 668, 716, 280, 0, 628, + 334, 686, 370, 223, 289, 287, 396, 246, 240, 236, + 222, 265, 294, 332, 387, 326, 723, 284, 675, 0, + 379, 306, 0, 0, 0, 656, 706, 663, 697, 651, + 685, 612, 674, 718, 639, 682, 719, 270, 221, 192, + 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, + 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, + 679, 713, 636, 681, 233, 268, 239, 232, 394, 683, + 729, 599, 676, 0, 602, 605, 725, 709, 631, 632, + 0, 0, 0, 0, 0, 0, 0, 655, 664, 694, + 649, 0, 0, 0, 0, 0, 0, 1674, 0, 629, + 0, 673, 0, 0, 0, 608, 603, 0, 0, 0, + 0, 653, 0, 0, 0, 611, 0, 630, 695, 0, + 597, 256, 606, 307, 699, 708, 650, 421, 712, 648, + 647, 715, 690, 609, 705, 642, 279, 607, 276, 188, + 202, 0, 640, 317, 355, 360, 704, 626, 635, 224, + 633, 358, 330, 409, 209, 247, 352, 335, 356, 672, + 688, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, @@ -2380,42 +1806,88 @@ var yyAct = [...]int{ 225, 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, - 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, + 413, 434, 211, 621, 700, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, - 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, - 329, 359, 215, 411, 378, 534, 545, 540, 541, 538, - 539, 0, 537, 536, 535, 548, 526, 527, 528, 529, - 531, 0, 542, 543, 530, 187, 200, 282, 0, 349, - 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, + 342, 259, 312, 206, 264, 377, 277, 286, 692, 728, + 329, 359, 215, 411, 378, 616, 620, 614, 615, 666, + 667, 617, 720, 721, 722, 696, 610, 0, 618, 619, + 0, 702, 710, 711, 671, 187, 200, 282, 724, 349, + 250, 432, 416, 414, 598, 613, 230, 624, 0, 0, + 637, 644, 645, 657, 659, 660, 661, 662, 670, 677, + 678, 680, 687, 689, 691, 693, 698, 707, 727, 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, - 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, + 669, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, - 390, 392, 303, 234, 321, 0, 0, 0, 0, 0, - 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, - 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, - 240, 236, 222, 265, 294, 332, 387, 326, 533, 284, - 0, 0, 379, 306, 0, 0, 0, 0, 0, 524, - 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, - 221, 192, 318, 380, 249, 67, 0, 0, 174, 175, - 176, 511, 510, 513, 514, 515, 516, 0, 0, 213, - 512, 219, 517, 518, 519, 0, 233, 268, 239, 232, - 394, 0, 0, 0, 0, 504, 0, 532, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 501, 502, 0, - 0, 0, 0, 547, 0, 503, 0, 0, 496, 497, - 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 256, 0, 307, 546, 0, 0, 421, - 0, 0, 544, 0, 0, 0, 0, 0, 279, 0, - 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, - 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, - 356, 2080, 0, 357, 285, 398, 347, 408, 422, 423, + 390, 392, 303, 234, 714, 701, 0, 0, 652, 717, + 623, 641, 726, 643, 646, 684, 604, 665, 321, 638, + 0, 627, 600, 634, 601, 625, 654, 237, 658, 622, + 703, 668, 716, 280, 0, 628, 334, 686, 370, 223, + 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, + 387, 326, 723, 284, 675, 0, 379, 306, 0, 0, + 0, 656, 706, 663, 697, 651, 685, 612, 674, 718, + 639, 682, 719, 270, 221, 192, 318, 380, 249, 0, + 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, + 0, 0, 0, 213, 0, 219, 679, 713, 636, 681, + 233, 268, 239, 232, 394, 683, 729, 599, 676, 0, + 602, 605, 725, 709, 631, 632, 0, 0, 0, 0, + 0, 0, 0, 655, 664, 694, 649, 0, 0, 0, + 0, 0, 0, 1399, 0, 629, 0, 673, 0, 0, + 0, 608, 603, 0, 0, 0, 0, 653, 0, 0, + 0, 611, 0, 630, 695, 0, 597, 256, 606, 307, + 699, 708, 650, 421, 712, 648, 647, 715, 690, 609, + 705, 642, 279, 607, 276, 188, 202, 0, 640, 317, + 355, 360, 704, 626, 635, 224, 633, 358, 330, 409, + 209, 247, 352, 335, 356, 672, 688, 357, 285, 398, + 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, + 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, + 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, + 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, + 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, + 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, + 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, + 308, 310, 0, 193, 0, 381, 413, 434, 211, 621, + 700, 393, 427, 430, 0, 348, 212, 253, 244, 344, + 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, + 264, 377, 277, 286, 692, 728, 329, 359, 215, 411, + 378, 616, 620, 614, 615, 666, 667, 617, 720, 721, + 722, 696, 610, 0, 618, 619, 0, 702, 710, 711, + 671, 187, 200, 282, 724, 349, 250, 432, 416, 414, + 598, 613, 230, 624, 0, 0, 637, 644, 645, 657, + 659, 660, 661, 662, 670, 677, 678, 680, 687, 689, + 691, 693, 698, 707, 727, 189, 190, 201, 208, 217, + 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, + 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, + 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, + 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, + 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, + 424, 258, 407, 425, 0, 290, 669, 194, 220, 207, + 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, + 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, + 714, 701, 0, 0, 652, 717, 623, 641, 726, 643, + 646, 684, 604, 665, 321, 638, 0, 627, 600, 634, + 601, 625, 654, 237, 658, 622, 703, 668, 716, 280, + 0, 628, 334, 686, 370, 223, 289, 287, 396, 246, + 240, 236, 222, 265, 294, 332, 387, 326, 723, 284, + 675, 0, 379, 306, 0, 0, 0, 656, 706, 663, + 697, 651, 685, 612, 674, 718, 639, 682, 719, 270, + 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, + 176, 0, 0, 0, 0, 0, 0, 0, 0, 213, + 0, 219, 679, 713, 636, 681, 233, 268, 239, 232, + 394, 683, 729, 599, 676, 0, 602, 605, 725, 709, + 631, 632, 0, 0, 0, 0, 0, 0, 0, 655, + 664, 694, 649, 0, 0, 0, 0, 0, 0, 0, + 0, 629, 0, 673, 0, 0, 0, 608, 603, 0, + 0, 0, 0, 653, 0, 0, 0, 611, 0, 630, + 695, 0, 597, 256, 606, 307, 699, 708, 650, 421, + 712, 648, 647, 715, 690, 609, 705, 642, 279, 607, + 276, 188, 202, 0, 640, 317, 355, 360, 704, 626, + 635, 224, 633, 358, 330, 409, 209, 247, 352, 335, + 356, 672, 688, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, @@ -2423,82 +1895,259 @@ var yyAct = [...]int{ 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, - 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, + 0, 381, 413, 434, 211, 621, 700, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, - 0, 0, 329, 359, 215, 411, 378, 534, 545, 540, - 541, 538, 539, 0, 537, 536, 535, 548, 526, 527, - 528, 529, 531, 0, 542, 543, 530, 187, 200, 282, - 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 189, 190, 201, 208, 217, 229, 242, 248, 257, + 692, 728, 329, 359, 215, 411, 378, 616, 620, 614, + 615, 666, 667, 617, 720, 721, 722, 696, 610, 0, + 618, 619, 0, 702, 710, 711, 671, 187, 200, 282, + 724, 349, 250, 432, 416, 414, 598, 613, 230, 624, + 0, 0, 637, 644, 645, 657, 659, 660, 661, 662, + 670, 677, 678, 680, 687, 689, 691, 693, 698, 707, + 727, 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, - 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, + 0, 290, 669, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, - 388, 389, 390, 392, 303, 234, 321, 0, 0, 0, - 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, - 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, + 388, 389, 390, 392, 303, 234, 714, 701, 0, 0, + 652, 717, 623, 641, 726, 643, 646, 684, 604, 665, + 321, 638, 0, 627, 600, 634, 601, 625, 654, 237, + 658, 622, 703, 668, 716, 280, 0, 628, 334, 686, + 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, + 294, 332, 387, 326, 723, 284, 675, 0, 379, 306, + 0, 0, 0, 656, 706, 663, 697, 651, 685, 612, + 674, 718, 639, 682, 719, 270, 221, 192, 318, 380, + 249, 0, 0, 0, 174, 175, 176, 0, 0, 0, + 0, 0, 0, 0, 0, 213, 0, 219, 679, 713, + 636, 681, 233, 268, 239, 232, 394, 683, 729, 599, + 676, 0, 602, 605, 725, 709, 631, 632, 0, 0, + 0, 0, 0, 0, 0, 655, 664, 694, 649, 0, + 0, 0, 0, 0, 0, 0, 0, 629, 0, 673, + 0, 0, 0, 608, 603, 0, 0, 0, 0, 653, + 0, 0, 0, 611, 0, 630, 695, 0, 597, 256, + 606, 307, 699, 708, 650, 421, 712, 648, 647, 715, + 690, 609, 705, 642, 279, 607, 276, 188, 202, 0, + 640, 317, 355, 360, 704, 626, 635, 224, 633, 358, + 330, 409, 209, 247, 352, 335, 356, 672, 688, 357, + 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, + 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, + 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, + 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, + 0, 351, 235, 252, 226, 320, 401, 402, 225, 433, + 204, 418, 199, 731, 417, 313, 397, 405, 302, 293, + 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, + 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, + 211, 621, 700, 393, 427, 430, 0, 348, 212, 253, + 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, + 596, 730, 590, 589, 277, 286, 692, 728, 329, 359, + 215, 411, 378, 616, 620, 614, 615, 666, 667, 617, + 720, 721, 722, 696, 610, 0, 618, 619, 0, 702, + 710, 711, 671, 187, 200, 282, 724, 349, 250, 432, + 416, 414, 598, 613, 230, 624, 0, 0, 637, 644, + 645, 657, 659, 660, 661, 662, 670, 677, 678, 680, + 687, 689, 691, 693, 698, 707, 727, 189, 190, 201, + 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, + 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, + 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, + 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, + 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, + 410, 420, 424, 258, 407, 425, 0, 290, 669, 194, + 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, + 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, + 303, 234, 714, 701, 0, 0, 652, 717, 623, 641, + 726, 643, 646, 684, 604, 665, 321, 638, 0, 627, + 600, 634, 601, 625, 654, 237, 658, 622, 703, 668, + 716, 280, 0, 628, 334, 686, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, - 533, 284, 0, 0, 379, 306, 0, 0, 0, 0, - 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, - 0, 270, 221, 192, 318, 380, 249, 67, 0, 564, - 174, 175, 176, 511, 510, 513, 514, 515, 516, 0, - 0, 213, 512, 219, 517, 518, 519, 0, 233, 268, - 239, 232, 394, 0, 0, 0, 0, 504, 0, 532, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, - 502, 0, 0, 0, 0, 547, 0, 503, 0, 0, - 496, 497, 499, 498, 500, 505, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 256, 0, 307, 546, 0, - 0, 421, 0, 0, 544, 0, 0, 0, 0, 0, - 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, - 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, - 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, + 723, 284, 675, 0, 379, 306, 0, 0, 0, 656, + 706, 663, 697, 651, 685, 612, 674, 718, 639, 682, + 719, 270, 221, 192, 318, 380, 249, 0, 0, 0, + 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, + 0, 213, 0, 219, 679, 713, 636, 681, 233, 268, + 239, 232, 394, 683, 729, 599, 676, 0, 602, 605, + 725, 709, 631, 632, 0, 0, 0, 0, 0, 0, + 0, 655, 664, 694, 649, 0, 0, 0, 0, 0, + 0, 0, 0, 629, 0, 673, 0, 0, 0, 608, + 603, 0, 0, 0, 0, 653, 0, 0, 0, 611, + 0, 630, 695, 0, 597, 256, 606, 307, 699, 708, + 650, 421, 712, 648, 647, 715, 690, 609, 705, 642, + 279, 607, 276, 188, 202, 0, 640, 317, 355, 360, + 704, 626, 635, 224, 633, 358, 330, 409, 209, 247, + 352, 335, 356, 672, 688, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, - 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, + 283, 195, 386, 1045, 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, - 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, + 226, 320, 401, 402, 225, 433, 204, 418, 199, 731, 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, - 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, + 0, 193, 0, 381, 413, 434, 211, 621, 700, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, - 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, - 277, 286, 0, 0, 329, 359, 215, 411, 378, 534, - 545, 540, 541, 538, 539, 0, 537, 536, 535, 548, - 526, 527, 528, 529, 531, 0, 542, 543, 530, 187, - 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, + 426, 428, 429, 210, 342, 259, 596, 730, 590, 589, + 277, 286, 692, 728, 329, 359, 215, 411, 378, 616, + 620, 614, 615, 666, 667, 617, 720, 721, 722, 696, + 610, 0, 618, 619, 0, 702, 710, 711, 671, 187, + 200, 282, 724, 349, 250, 432, 416, 414, 598, 613, + 230, 624, 0, 0, 637, 644, 645, 657, 659, 660, + 661, 662, 670, 677, 678, 680, 687, 689, 691, 693, + 698, 707, 727, 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, - 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, + 407, 425, 0, 290, 669, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, - 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, - 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, - 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, + 216, 369, 388, 389, 390, 392, 303, 234, 714, 701, + 0, 0, 652, 717, 623, 641, 726, 643, 646, 684, + 604, 665, 321, 638, 0, 627, 600, 634, 601, 625, + 654, 237, 658, 622, 703, 668, 716, 280, 0, 628, + 334, 686, 370, 223, 289, 287, 396, 246, 240, 236, + 222, 265, 294, 332, 387, 326, 723, 284, 675, 0, + 379, 306, 0, 0, 0, 656, 706, 663, 697, 651, + 685, 612, 674, 718, 639, 682, 719, 270, 221, 192, + 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, + 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, + 679, 713, 636, 681, 233, 268, 239, 232, 394, 683, + 729, 599, 676, 0, 602, 605, 725, 709, 631, 632, + 0, 0, 0, 0, 0, 0, 0, 655, 664, 694, + 649, 0, 0, 0, 0, 0, 0, 0, 0, 629, + 0, 673, 0, 0, 0, 608, 603, 0, 0, 0, + 0, 653, 0, 0, 0, 611, 0, 630, 695, 0, + 597, 256, 606, 307, 699, 708, 650, 421, 712, 648, + 647, 715, 690, 609, 705, 642, 279, 607, 276, 188, + 202, 0, 640, 317, 355, 360, 704, 626, 635, 224, + 633, 358, 330, 409, 209, 247, 352, 335, 356, 672, + 688, 357, 285, 398, 347, 408, 422, 423, 231, 311, + 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, + 304, 395, 275, 375, 254, 191, 283, 195, 386, 587, + 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, + 273, 196, 0, 351, 235, 252, 226, 320, 401, 402, + 225, 433, 204, 418, 199, 731, 417, 313, 397, 405, + 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, + 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, + 413, 434, 211, 621, 700, 393, 427, 430, 0, 348, + 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, + 342, 259, 596, 730, 590, 589, 277, 286, 692, 728, + 329, 359, 215, 411, 378, 616, 620, 614, 615, 666, + 667, 617, 720, 721, 722, 696, 610, 0, 618, 619, + 0, 702, 710, 711, 671, 187, 200, 282, 724, 349, + 250, 432, 416, 414, 598, 613, 230, 624, 0, 0, + 637, 644, 645, 657, 659, 660, 661, 662, 670, 677, + 678, 680, 687, 689, 691, 693, 698, 707, 727, 189, + 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, + 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, + 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, + 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, + 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, + 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, + 669, 194, 220, 207, 227, 241, 243, 271, 299, 305, + 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, + 390, 392, 303, 234, 321, 0, 0, 1328, 0, 490, + 0, 0, 0, 237, 0, 489, 0, 0, 0, 280, + 0, 1329, 334, 0, 370, 223, 289, 287, 396, 246, + 240, 236, 222, 265, 294, 332, 387, 326, 533, 284, + 0, 0, 379, 306, 0, 0, 0, 0, 0, 524, + 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, + 221, 192, 318, 380, 249, 67, 0, 0, 174, 175, + 176, 511, 510, 513, 514, 515, 516, 0, 0, 213, + 512, 219, 517, 518, 519, 0, 233, 268, 239, 232, + 394, 0, 0, 0, 487, 504, 0, 532, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 501, 502, 577, + 0, 0, 0, 548, 0, 503, 0, 0, 496, 497, + 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 256, 0, 307, 547, 0, 0, 421, + 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, + 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, + 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, + 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, + 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, + 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, + 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, + 301, 272, 273, 196, 0, 351, 235, 252, 226, 320, + 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, + 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, + 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, + 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, + 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, + 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, + 0, 0, 329, 359, 215, 411, 378, 535, 546, 541, + 542, 539, 540, 534, 538, 537, 536, 549, 526, 527, + 528, 529, 531, 0, 543, 544, 530, 187, 200, 282, + 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 189, 190, 201, 208, 217, 229, 242, 248, 257, + 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, + 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, + 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, + 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, + 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, + 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, + 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, + 388, 389, 390, 392, 303, 234, 321, 0, 0, 0, + 0, 490, 0, 0, 0, 237, 0, 489, 0, 0, + 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, + 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, + 533, 284, 0, 0, 379, 306, 0, 0, 0, 0, + 0, 524, 525, 0, 0, 0, 0, 0, 0, 1438, + 0, 270, 221, 192, 318, 380, 249, 67, 0, 0, + 174, 175, 176, 511, 510, 513, 514, 515, 516, 0, + 0, 213, 512, 219, 517, 518, 519, 1439, 233, 268, + 239, 232, 394, 0, 0, 0, 487, 504, 0, 532, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 501, + 502, 0, 0, 0, 0, 548, 0, 503, 0, 0, + 496, 497, 499, 498, 500, 505, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 256, 0, 307, 547, 0, + 0, 421, 0, 0, 545, 0, 0, 0, 0, 0, + 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, + 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, + 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, + 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, + 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, + 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, + 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, + 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, + 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, + 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, + 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, + 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, + 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, + 277, 286, 0, 0, 329, 359, 215, 411, 378, 535, + 546, 541, 542, 539, 540, 534, 538, 537, 536, 549, + 526, 527, 528, 529, 531, 0, 543, 544, 530, 187, + 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, + 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, + 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, + 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, + 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, + 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, + 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, + 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, + 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, + 0, 0, 0, 490, 0, 0, 0, 237, 0, 489, + 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 533, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, 67, - 0, 0, 174, 175, 176, 511, 510, 513, 514, 515, + 0, 565, 174, 175, 176, 511, 510, 513, 514, 515, 516, 0, 0, 213, 512, 219, 517, 518, 519, 0, - 233, 268, 239, 232, 394, 0, 0, 0, 0, 504, + 233, 268, 239, 232, 394, 0, 0, 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 501, 502, 0, 0, 0, 0, 547, 0, 503, + 0, 501, 502, 0, 0, 0, 0, 548, 0, 503, 0, 0, 496, 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, - 546, 0, 0, 421, 0, 0, 544, 0, 0, 0, + 547, 0, 0, 421, 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, @@ -2513,8 +2162,8 @@ var yyAct = [...]int{ 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, - 378, 534, 545, 540, 541, 538, 539, 0, 537, 536, - 535, 548, 526, 527, 528, 529, 531, 0, 542, 543, + 378, 535, 546, 541, 542, 539, 540, 534, 538, 537, + 536, 549, 526, 527, 528, 529, 531, 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2527,21 +2176,21 @@ var yyAct = [...]int{ 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, - 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, - 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, + 321, 0, 0, 0, 0, 490, 0, 0, 0, 237, + 0, 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 294, 332, 387, 326, 533, 284, 0, 0, 379, 306, + 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 0, 0, 0, 174, 175, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, - 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, + 249, 67, 0, 0, 174, 175, 176, 511, 510, 513, + 514, 515, 516, 0, 0, 213, 512, 219, 517, 518, + 519, 0, 233, 268, 239, 232, 394, 0, 0, 0, + 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 921, - 920, 930, 931, 923, 924, 925, 926, 927, 928, 929, - 922, 0, 0, 932, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 501, 502, 577, 0, 0, 0, 548, + 0, 503, 0, 0, 496, 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, - 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, + 0, 307, 547, 0, 0, 421, 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, @@ -2556,9 +2205,9 @@ var yyAct = [...]int{ 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, - 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 200, 282, 0, 349, 250, 432, + 215, 411, 378, 535, 546, 541, 542, 539, 540, 534, + 538, 537, 536, 549, 526, 527, 528, 529, 531, 0, + 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, @@ -2570,23 +2219,23 @@ var yyAct = [...]int{ 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, - 303, 234, 321, 0, 0, 0, 0, 0, 0, 0, - 0, 237, 771, 0, 0, 0, 0, 280, 0, 0, + 303, 234, 321, 0, 0, 0, 0, 490, 0, 0, + 0, 237, 0, 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, - 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, - 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, + 222, 265, 294, 332, 387, 326, 533, 284, 0, 0, + 379, 306, 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, - 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, - 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, - 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 318, 380, 249, 67, 0, 0, 174, 175, 176, 511, + 1346, 513, 514, 515, 516, 0, 0, 213, 512, 219, + 517, 518, 519, 0, 233, 268, 239, 232, 394, 0, + 0, 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 256, 0, 307, 0, 0, 770, 421, 0, 0, - 0, 0, 0, 0, 767, 768, 279, 738, 276, 188, - 202, 761, 765, 317, 355, 360, 0, 0, 0, 224, + 0, 0, 0, 0, 0, 501, 502, 577, 0, 0, + 0, 548, 0, 503, 0, 0, 496, 497, 499, 498, + 500, 505, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 256, 0, 307, 547, 0, 0, 421, 0, 0, + 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, + 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, @@ -2599,9 +2248,9 @@ var yyAct = [...]int{ 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, - 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 187, 200, 282, 0, 349, + 329, 359, 215, 411, 378, 535, 546, 541, 542, 539, + 540, 534, 538, 537, 536, 549, 526, 527, 528, 529, + 531, 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, @@ -2613,22 +2262,22 @@ var yyAct = [...]int{ 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, - 390, 392, 303, 234, 321, 0, 0, 0, 1021, 0, - 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, + 390, 392, 303, 234, 321, 0, 0, 0, 0, 490, + 0, 0, 0, 237, 0, 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, - 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, - 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, - 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, - 176, 0, 1023, 0, 0, 0, 0, 0, 0, 213, - 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, - 394, 910, 911, 909, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 912, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 240, 236, 222, 265, 294, 332, 387, 326, 533, 284, + 0, 0, 379, 306, 0, 0, 0, 0, 0, 524, + 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, + 221, 192, 318, 380, 249, 67, 0, 0, 174, 175, + 176, 511, 1343, 513, 514, 515, 516, 0, 0, 213, + 512, 219, 517, 518, 519, 0, 233, 268, 239, 232, + 394, 0, 0, 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 256, 0, 307, 0, 0, 0, 421, - 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, + 0, 0, 0, 0, 0, 0, 0, 501, 502, 577, + 0, 0, 0, 548, 0, 503, 0, 0, 496, 497, + 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 256, 0, 307, 547, 0, 0, 421, + 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, @@ -2642,9 +2291,9 @@ var yyAct = [...]int{ 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, - 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 200, 282, + 0, 0, 329, 359, 215, 411, 378, 535, 546, 541, + 542, 539, 540, 534, 538, 537, 536, 549, 526, 527, + 528, 529, 531, 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2656,23 +2305,23 @@ var yyAct = [...]int{ 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, - 388, 389, 390, 392, 303, 234, 33, 0, 0, 0, + 388, 389, 390, 392, 303, 234, 558, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 321, - 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, - 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, + 0, 0, 0, 0, 490, 0, 0, 0, 237, 0, + 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, - 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 332, 387, 326, 533, 284, 0, 0, 379, 306, 0, + 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, - 67, 0, 564, 174, 175, 176, 0, 0, 0, 0, - 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, - 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 67, 0, 0, 174, 175, 176, 511, 510, 513, 514, + 515, 516, 0, 0, 213, 512, 219, 517, 518, 519, + 0, 233, 268, 239, 232, 394, 0, 0, 0, 487, + 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 501, 502, 0, 0, 0, 0, 548, 0, + 503, 0, 0, 496, 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, - 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, + 307, 547, 0, 0, 421, 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, @@ -2687,9 +2336,9 @@ var yyAct = [...]int{ 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, - 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, + 411, 378, 535, 546, 541, 542, 539, 540, 534, 538, + 537, 536, 549, 526, 527, 528, 529, 531, 0, 543, + 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, @@ -2701,24 +2350,24 @@ var yyAct = [...]int{ 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, - 234, 321, 0, 0, 0, 1371, 0, 0, 0, 0, - 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, + 234, 321, 0, 0, 0, 0, 490, 0, 0, 0, + 237, 0, 489, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, - 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, - 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 265, 294, 332, 387, 326, 533, 284, 0, 0, 379, + 306, 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, - 380, 249, 0, 0, 0, 174, 175, 176, 0, 1373, - 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, - 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 380, 249, 67, 0, 0, 174, 175, 176, 511, 510, + 513, 514, 515, 516, 0, 0, 213, 512, 219, 517, + 518, 519, 0, 233, 268, 239, 232, 394, 0, 0, + 0, 487, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 256, 0, 307, 0, 0, 0, 421, 0, 0, 0, + 0, 0, 0, 0, 501, 502, 0, 0, 0, 0, + 548, 0, 503, 0, 0, 496, 497, 499, 498, 500, + 505, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 256, 0, 307, 547, 0, 0, 421, 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, - 358, 330, 409, 209, 247, 352, 335, 356, 0, 1369, + 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, @@ -2730,9 +2379,9 @@ var yyAct = [...]int{ 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, - 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 187, 200, 282, 0, 349, 250, + 359, 215, 411, 378, 535, 546, 541, 542, 539, 540, + 534, 538, 537, 536, 549, 526, 527, 528, 529, 531, + 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, @@ -2747,22 +2396,22 @@ var yyAct = [...]int{ 392, 303, 234, 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, - 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, - 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, + 236, 222, 265, 294, 332, 387, 326, 533, 284, 0, + 0, 379, 306, 0, 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, - 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, - 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, - 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 732, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 192, 318, 380, 249, 67, 0, 0, 174, 175, 176, + 511, 510, 513, 514, 515, 516, 0, 0, 213, 512, + 219, 517, 518, 519, 0, 233, 268, 239, 232, 394, + 0, 0, 0, 0, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 256, 0, 307, 0, 0, 0, 421, 0, - 0, 0, 0, 0, 0, 0, 0, 279, 738, 276, - 188, 202, 736, 0, 317, 355, 360, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 501, 502, 0, 0, + 0, 0, 548, 0, 503, 0, 0, 496, 497, 499, + 498, 500, 505, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 256, 0, 307, 547, 0, 0, 421, 0, + 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, + 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, - 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, + 2082, 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, @@ -2773,9 +2422,9 @@ var yyAct = [...]int{ 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, - 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 187, 200, 282, 0, + 0, 329, 359, 215, 411, 378, 535, 546, 541, 542, + 539, 540, 534, 538, 537, 536, 549, 526, 527, 528, + 529, 531, 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2787,22 +2436,22 @@ var yyAct = [...]int{ 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, - 389, 390, 392, 303, 234, 321, 0, 0, 0, 1371, + 389, 390, 392, 303, 234, 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, - 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, + 246, 240, 236, 222, 265, 294, 332, 387, 326, 533, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, + 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, + 270, 221, 192, 318, 380, 249, 67, 0, 565, 174, + 175, 176, 511, 510, 513, 514, 515, 516, 0, 0, + 213, 512, 219, 517, 518, 519, 0, 233, 268, 239, + 232, 394, 0, 0, 0, 0, 504, 0, 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, - 175, 176, 0, 1373, 0, 0, 0, 0, 0, 0, - 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, - 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 256, 0, 307, 0, 0, 0, - 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, + 0, 0, 0, 0, 0, 0, 0, 0, 501, 502, + 0, 0, 0, 0, 548, 0, 503, 0, 0, 496, + 497, 499, 498, 500, 505, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 256, 0, 307, 547, 0, 0, + 421, 0, 0, 545, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, @@ -2816,9 +2465,9 @@ var yyAct = [...]int{ 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 200, + 286, 0, 0, 329, 359, 215, 411, 378, 535, 546, + 541, 542, 539, 540, 534, 538, 537, 536, 549, 526, + 527, 528, 529, 531, 0, 543, 544, 530, 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2830,17 +2479,233 @@ var yyAct = [...]int{ 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 33, 0, 0, + 369, 388, 389, 390, 392, 303, 234, 321, 0, 0, + 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, + 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, + 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, + 326, 533, 284, 0, 0, 379, 306, 0, 0, 0, + 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, + 0, 0, 270, 221, 192, 318, 380, 249, 67, 0, + 0, 174, 175, 176, 511, 510, 513, 514, 515, 516, + 0, 0, 213, 512, 219, 517, 518, 519, 0, 233, + 268, 239, 232, 394, 0, 0, 0, 0, 504, 0, + 532, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, - 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, - 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, + 501, 502, 0, 0, 0, 0, 548, 0, 503, 0, + 0, 496, 497, 499, 498, 500, 505, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 256, 0, 307, 547, + 0, 0, 421, 0, 0, 545, 0, 0, 0, 0, + 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, + 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, + 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, + 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, + 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, + 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, + 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, + 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, + 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, + 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, + 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, + 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, + 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, + 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, + 535, 546, 541, 542, 539, 540, 534, 538, 537, 536, + 549, 526, 527, 528, 529, 531, 0, 543, 544, 530, + 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, + 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 67, 0, 0, 174, 175, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, - 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, + 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, + 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, + 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, + 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, + 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, + 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, + 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, + 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, + 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, + 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, + 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, + 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, + 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, + 0, 0, 0, 174, 175, 176, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, + 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 922, 921, + 931, 932, 924, 925, 926, 927, 928, 929, 930, 923, + 0, 0, 933, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, + 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, + 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, + 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, + 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, + 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, + 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, + 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, + 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, + 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, + 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, + 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, + 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, + 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, + 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, + 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, + 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, + 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, + 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, + 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, + 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, + 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, + 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, + 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, + 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, + 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, + 234, 321, 0, 0, 0, 0, 0, 0, 0, 0, + 237, 772, 0, 0, 0, 0, 280, 0, 0, 334, + 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, + 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, + 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, + 380, 249, 0, 0, 0, 174, 175, 176, 0, 0, + 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, + 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 256, 0, 307, 0, 0, 771, 421, 0, 0, 0, + 0, 0, 0, 768, 769, 279, 739, 276, 188, 202, + 762, 766, 317, 355, 360, 0, 0, 0, 224, 0, + 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, + 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, + 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, + 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, + 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, + 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, + 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, + 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, + 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, + 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, + 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, + 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, + 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 200, 282, 0, 349, 250, + 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, + 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, + 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, + 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, + 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, + 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, + 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, + 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, + 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, + 392, 303, 234, 321, 0, 0, 0, 1023, 0, 0, + 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, + 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, + 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, + 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, + 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, + 0, 1025, 0, 0, 0, 0, 0, 0, 213, 0, + 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, + 911, 912, 910, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 913, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 256, 0, 307, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 279, 0, 276, + 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, + 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, + 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, + 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, + 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, + 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, + 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, + 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, + 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, + 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, + 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, + 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, + 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, + 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 200, 282, 0, + 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, + 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, + 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, + 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, + 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, + 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, + 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, + 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, + 389, 390, 392, 303, 234, 33, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 321, 0, + 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, + 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, + 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, + 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 270, 221, 192, 318, 380, 249, 67, + 0, 565, 174, 175, 176, 0, 0, 0, 0, 0, + 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, + 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, + 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, + 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, + 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, + 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, + 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, + 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, + 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, + 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, + 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, + 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, + 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, + 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, + 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, + 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, + 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, + 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, + 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, + 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, + 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, + 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, + 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, + 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, + 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, + 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, + 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, + 321, 0, 0, 0, 1373, 0, 0, 0, 0, 237, + 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, + 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, + 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, + 249, 0, 0, 0, 174, 175, 176, 0, 1375, 0, + 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, + 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2849,7 +2714,7 @@ var yyAct = [...]int{ 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, - 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, + 330, 409, 209, 247, 352, 335, 356, 0, 1371, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, @@ -2882,16 +2747,16 @@ var yyAct = [...]int{ 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, - 0, 1389, 0, 0, 1390, 0, 0, 213, 0, 219, + 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 733, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, 0, 0, 0, 421, 0, 0, - 0, 0, 0, 0, 0, 0, 279, 0, 276, 188, - 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, + 0, 0, 0, 0, 0, 0, 279, 739, 276, 188, + 202, 737, 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, @@ -2918,14 +2783,14 @@ var yyAct = [...]int{ 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, - 390, 392, 303, 234, 321, 0, 0, 0, 0, 0, - 0, 0, 0, 237, 0, 1054, 0, 0, 0, 280, + 390, 392, 303, 234, 321, 0, 0, 0, 1373, 0, + 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, - 176, 0, 1053, 0, 0, 0, 0, 0, 0, 213, + 176, 0, 1375, 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -2961,570 +2826,441 @@ var yyAct = [...]int{ 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, - 388, 389, 390, 392, 303, 234, 321, 0, 0, 0, - 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, - 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, - 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, - 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 270, 221, 192, 318, 380, 249, 0, 0, 564, - 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, - 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, - 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 388, 389, 390, 392, 303, 234, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 321, + 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, + 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, + 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, + 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, + 67, 0, 0, 174, 175, 176, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, + 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 256, 0, 307, 0, 0, - 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, - 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, - 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, - 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, - 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, - 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, - 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, - 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, - 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, - 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, - 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, - 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, - 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, - 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, - 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, - 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, - 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, - 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, - 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, - 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, - 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, - 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, - 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, - 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, - 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, - 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, - 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, - 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 270, 221, 192, 318, 380, 249, 67, - 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, - 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, - 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, + 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, + 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, + 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, + 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, + 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, + 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, + 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, + 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, + 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, + 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, + 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, + 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, + 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, + 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, + 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, + 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, + 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, - 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, - 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, - 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, - 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, - 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, - 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, - 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, - 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, - 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, - 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, - 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, - 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, - 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, - 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, - 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, - 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, - 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, - 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, - 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, - 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, - 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, - 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, - 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, - 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, - 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, - 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, - 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, - 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 0, 0, 0, 174, 175, 176, 0, 1373, 0, - 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, - 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, - 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, - 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, - 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, - 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, - 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, - 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, - 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, - 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, - 0, 351, 235, 252, 226, 320, 401, 402, 225, 433, - 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, - 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, - 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, - 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, - 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, - 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, - 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 200, 282, 0, 349, 250, 432, - 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, - 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, - 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, - 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, - 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, - 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, - 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, - 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, - 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, - 303, 234, 321, 0, 0, 0, 0, 0, 0, 0, - 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, - 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, - 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, - 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, - 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, - 1023, 0, 0, 0, 0, 0, 0, 213, 0, 219, - 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, + 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, + 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, + 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, + 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, + 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, + 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, + 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, + 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, + 234, 321, 0, 0, 0, 0, 0, 0, 0, 0, + 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, + 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, + 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, + 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, + 380, 249, 0, 0, 0, 174, 175, 176, 0, 0, + 1391, 0, 0, 1392, 0, 0, 213, 0, 219, 0, + 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 256, 0, 307, 0, 0, 0, 421, 0, 0, - 0, 0, 0, 0, 0, 0, 279, 0, 276, 188, - 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, - 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, - 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, - 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, - 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, - 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, - 273, 196, 0, 351, 235, 252, 226, 320, 401, 402, - 225, 433, 204, 418, 199, 205, 417, 313, 397, 405, - 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, - 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, - 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, - 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, - 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, - 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 187, 200, 282, 0, 349, - 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, + 256, 0, 307, 0, 0, 0, 421, 0, 0, 0, + 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, + 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, + 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, + 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, + 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, + 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, + 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, + 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, + 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, + 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, + 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, + 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, + 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, + 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, + 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, - 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, - 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, - 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, - 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, - 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, - 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, - 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, - 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, - 390, 392, 303, 234, 321, 0, 1173, 0, 0, 0, - 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, - 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, - 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, - 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, - 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, - 176, 0, 0, 0, 0, 0, 0, 0, 0, 213, - 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, - 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 200, 282, 0, 349, 250, + 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, + 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, + 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, + 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, + 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, + 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, + 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, + 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, + 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, + 392, 303, 234, 321, 0, 0, 0, 0, 0, 0, + 0, 0, 237, 0, 1056, 0, 0, 0, 280, 0, + 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, + 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, + 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, + 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, + 0, 1055, 0, 0, 0, 0, 0, 0, 213, 0, + 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 256, 0, 307, 0, 0, 0, 421, - 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, - 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, - 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, - 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, - 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, - 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, - 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, - 301, 272, 273, 196, 0, 351, 235, 252, 226, 320, - 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, - 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, - 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, - 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, - 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, - 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, - 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 200, 282, - 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 256, 0, 307, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 279, 0, 276, + 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, + 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, + 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, + 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, + 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, + 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, + 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, + 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, + 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, + 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, + 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, + 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, + 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, + 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 189, 190, 201, 208, 217, 229, 242, 248, 257, - 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, - 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, - 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, - 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, - 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, - 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, - 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, - 388, 389, 390, 392, 303, 234, 321, 0, 1171, 0, - 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, - 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, - 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, - 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 200, 282, 0, + 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, - 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, - 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, - 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, + 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, + 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, + 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, + 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, + 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, + 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, + 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, + 389, 390, 392, 303, 234, 321, 0, 0, 0, 0, + 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, + 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, + 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, + 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 270, 221, 192, 318, 380, 249, 0, 0, 565, 174, + 175, 176, 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, + 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 256, 0, 307, 0, 0, - 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, - 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, - 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, - 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, - 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, - 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, - 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, - 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, - 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, - 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, - 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, - 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, - 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, - 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, - 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, - 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, - 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, - 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, - 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, - 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, - 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, - 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, - 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, - 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, - 1169, 0, 0, 0, 0, 0, 0, 237, 0, 0, - 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, - 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, - 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, + 0, 0, 0, 0, 256, 0, 307, 0, 0, 0, + 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, + 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, + 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, + 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, + 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, + 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, + 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, + 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, + 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, + 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, + 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, + 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, + 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, + 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, + 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, - 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, - 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, - 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 200, + 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, + 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, + 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, + 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, + 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, + 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, + 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, + 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, + 369, 388, 389, 390, 392, 303, 234, 321, 0, 0, + 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, + 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, + 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, + 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 270, 221, 192, 318, 380, 249, 67, 0, + 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, + 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, + 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, - 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, - 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, - 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, - 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, - 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, - 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, - 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, - 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, - 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, - 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, - 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, - 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, - 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, - 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, - 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, - 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, - 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, - 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, - 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, - 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, - 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, - 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, - 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, - 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, - 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, - 321, 0, 1167, 0, 0, 0, 0, 0, 0, 237, - 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, - 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 0, 0, 0, 174, 175, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, - 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 256, 0, 307, 0, + 0, 0, 421, 0, 0, 0, 0, 0, 0, 0, + 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, + 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, + 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, + 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, + 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, + 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, + 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, + 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, + 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, + 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, + 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, + 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, + 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, + 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, + 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, + 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, + 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, + 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, + 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, + 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, + 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, + 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, + 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, + 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, + 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, + 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, + 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, - 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, - 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, - 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, - 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, - 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, - 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, - 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, - 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, - 0, 351, 235, 252, 226, 320, 401, 402, 225, 433, - 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, - 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, - 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, - 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, - 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, - 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, - 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, + 0, 0, 0, 174, 175, 176, 0, 1375, 0, 0, + 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, + 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 200, 282, 0, 349, 250, 432, - 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, - 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, - 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, - 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, - 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, - 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, - 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, - 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, - 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, - 303, 234, 321, 0, 1165, 0, 0, 0, 0, 0, - 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, - 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, - 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, - 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, - 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, - 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, - 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, + 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, + 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, + 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, + 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, + 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, + 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, + 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, + 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, + 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, + 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, + 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, + 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, + 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, + 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, + 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, + 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, + 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, + 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, + 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, + 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, + 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, + 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, + 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, + 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, + 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, + 234, 321, 0, 0, 0, 0, 0, 0, 0, 0, + 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, + 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, + 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, + 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, + 380, 249, 0, 0, 0, 174, 175, 176, 0, 1025, + 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, + 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 256, 0, 307, 0, 0, 0, 421, 0, 0, - 0, 0, 0, 0, 0, 0, 279, 0, 276, 188, - 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, - 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, - 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, - 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, - 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, - 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, - 273, 196, 0, 351, 235, 252, 226, 320, 401, 402, - 225, 433, 204, 418, 199, 205, 417, 313, 397, 405, - 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, - 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, - 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, - 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, - 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, - 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 187, 200, 282, 0, 349, - 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, - 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, - 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, - 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, - 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, - 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, - 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, - 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, - 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, - 390, 392, 303, 234, 321, 0, 1161, 0, 0, 0, - 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, - 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, - 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, - 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, - 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, - 176, 0, 0, 0, 0, 0, 0, 0, 0, 213, - 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, - 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 256, 0, 307, 0, 0, 0, 421, 0, 0, 0, + 0, 0, 0, 0, 0, 279, 0, 276, 188, 202, + 0, 0, 317, 355, 360, 0, 0, 0, 224, 0, + 358, 330, 409, 209, 247, 352, 335, 356, 0, 0, + 357, 285, 398, 347, 408, 422, 423, 231, 311, 415, + 391, 419, 431, 203, 228, 324, 384, 412, 376, 304, + 395, 275, 375, 254, 191, 283, 195, 386, 406, 214, + 368, 0, 0, 0, 197, 404, 383, 301, 272, 273, + 196, 0, 351, 235, 252, 226, 320, 401, 402, 225, + 433, 204, 418, 199, 205, 417, 313, 397, 405, 302, + 293, 198, 403, 300, 292, 278, 245, 261, 345, 288, + 346, 262, 309, 308, 310, 0, 193, 0, 381, 413, + 434, 211, 0, 0, 393, 427, 430, 0, 348, 212, + 253, 244, 344, 251, 281, 426, 428, 429, 210, 342, + 259, 312, 206, 264, 377, 277, 286, 0, 0, 329, + 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 187, 200, 282, 0, 349, 250, + 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 256, 0, 307, 0, 0, 0, 421, - 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, - 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, - 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, - 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, - 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, - 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, - 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, - 301, 272, 273, 196, 0, 351, 235, 252, 226, 320, - 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, - 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, - 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, - 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, - 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, - 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, - 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 189, 190, + 201, 208, 217, 229, 242, 248, 257, 260, 263, 266, + 267, 269, 274, 291, 295, 296, 297, 298, 314, 315, + 316, 319, 322, 323, 325, 327, 328, 331, 337, 338, + 339, 340, 341, 343, 350, 354, 361, 362, 363, 364, + 365, 366, 367, 371, 372, 373, 374, 382, 385, 399, + 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, + 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, + 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, + 392, 303, 234, 321, 0, 1175, 0, 0, 0, 0, + 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, + 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, + 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, + 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, + 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, + 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, + 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 187, 200, 282, - 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 189, 190, 201, 208, 217, 229, 242, 248, 257, - 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, - 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, - 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, - 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, - 382, 385, 399, 400, 410, 420, 424, 258, 407, 425, - 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, - 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, - 388, 389, 390, 392, 303, 234, 321, 0, 1159, 0, - 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, - 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, - 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, - 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, - 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, - 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, - 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 256, 0, 307, 0, 0, 0, 421, 0, + 0, 0, 0, 0, 0, 0, 0, 279, 0, 276, + 188, 202, 0, 0, 317, 355, 360, 0, 0, 0, + 224, 0, 358, 330, 409, 209, 247, 352, 335, 356, + 0, 0, 357, 285, 398, 347, 408, 422, 423, 231, + 311, 415, 391, 419, 431, 203, 228, 324, 384, 412, + 376, 304, 395, 275, 375, 254, 191, 283, 195, 386, + 406, 214, 368, 0, 0, 0, 197, 404, 383, 301, + 272, 273, 196, 0, 351, 235, 252, 226, 320, 401, + 402, 225, 433, 204, 418, 199, 205, 417, 313, 397, + 405, 302, 293, 198, 403, 300, 292, 278, 245, 261, + 345, 288, 346, 262, 309, 308, 310, 0, 193, 0, + 381, 413, 434, 211, 0, 0, 393, 427, 430, 0, + 348, 212, 253, 244, 344, 251, 281, 426, 428, 429, + 210, 342, 259, 312, 206, 264, 377, 277, 286, 0, + 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 187, 200, 282, 0, + 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 256, 0, 307, 0, 0, - 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, - 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, - 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, - 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, - 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, - 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, - 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, - 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, - 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, - 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, - 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, - 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, - 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, - 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, - 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, + 189, 190, 201, 208, 217, 229, 242, 248, 257, 260, + 263, 266, 267, 269, 274, 291, 295, 296, 297, 298, + 314, 315, 316, 319, 322, 323, 325, 327, 328, 331, + 337, 338, 339, 340, 341, 343, 350, 354, 361, 362, + 363, 364, 365, 366, 367, 371, 372, 373, 374, 382, + 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, + 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, + 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, + 389, 390, 392, 303, 234, 321, 0, 1173, 0, 0, + 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, + 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, + 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, + 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, - 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, - 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, + 175, 176, 0, 0, 0, 0, 0, 0, 0, 0, + 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, + 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, - 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, - 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, - 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, - 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, - 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, - 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, - 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, - 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, - 1157, 0, 0, 0, 0, 0, 0, 237, 0, 0, - 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, - 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, - 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, - 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, - 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, - 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 256, 0, 307, 0, 0, 0, + 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, + 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, + 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, + 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, + 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, + 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, + 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, + 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, + 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, + 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, + 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, + 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, + 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, + 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, + 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 200, + 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, - 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, - 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, - 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, - 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, - 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, - 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, - 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, - 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, - 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, - 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, - 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, - 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, - 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, - 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, - 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, - 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, - 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, + 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, + 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, + 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, + 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, + 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, + 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, + 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, + 369, 388, 389, 390, 392, 303, 234, 321, 0, 1171, + 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, + 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, + 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, + 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, - 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, - 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, - 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, - 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, - 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, - 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, - 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, - 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, - 321, 0, 0, 0, 0, 0, 0, 0, 0, 237, - 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, - 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, - 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, + 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, + 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, + 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, + 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, - 249, 1132, 0, 0, 174, 175, 176, 0, 0, 0, - 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, - 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 256, 0, 307, 0, + 0, 0, 421, 0, 0, 0, 0, 0, 0, 0, + 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, + 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, + 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, + 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, + 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, + 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, + 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, + 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, + 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, + 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, + 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, + 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, + 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, + 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, - 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, - 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, - 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, - 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, - 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, - 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, - 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, - 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, - 0, 351, 235, 252, 226, 320, 401, 402, 225, 433, - 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, - 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, - 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, - 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, - 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, - 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, - 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 187, 200, 282, 0, 349, 250, 432, - 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, + 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, + 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, - 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, - 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, - 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, - 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, - 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, - 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, - 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, - 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, - 303, 234, 1036, 0, 0, 0, 0, 0, 0, 321, - 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, + 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, + 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, + 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, + 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, + 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, + 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, + 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, + 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, + 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, + 0, 1169, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, @@ -3567,7 +3303,7 @@ var yyAct = [...]int{ 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, - 234, 321, 0, 0, 0, 0, 0, 0, 0, 1027, + 234, 321, 0, 1167, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, @@ -3610,14 +3346,14 @@ var yyAct = [...]int{ 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, 390, - 392, 303, 234, 321, 0, 0, 0, 0, 0, 0, + 392, 303, 234, 321, 0, 1163, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, 176, - 0, 901, 0, 0, 0, 0, 0, 0, 213, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -3653,7 +3389,7 @@ var yyAct = [...]int{ 385, 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, 388, - 389, 390, 392, 303, 234, 321, 0, 0, 0, 0, + 389, 390, 392, 303, 234, 321, 0, 1161, 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, 0, @@ -3667,145 +3403,404 @@ var yyAct = [...]int{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 480, 0, 256, 0, 307, 0, 0, 0, - 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, - 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, - 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, - 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, - 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, - 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, - 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, - 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, - 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, - 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, - 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, - 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, - 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, - 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, - 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, + 0, 0, 0, 0, 256, 0, 307, 0, 0, 0, + 421, 0, 0, 0, 0, 0, 0, 0, 0, 279, + 0, 276, 188, 202, 0, 0, 317, 355, 360, 0, + 0, 0, 224, 0, 358, 330, 409, 209, 247, 352, + 335, 356, 0, 0, 357, 285, 398, 347, 408, 422, + 423, 231, 311, 415, 391, 419, 431, 203, 228, 324, + 384, 412, 376, 304, 395, 275, 375, 254, 191, 283, + 195, 386, 406, 214, 368, 0, 0, 0, 197, 404, + 383, 301, 272, 273, 196, 0, 351, 235, 252, 226, + 320, 401, 402, 225, 433, 204, 418, 199, 205, 417, + 313, 397, 405, 302, 293, 198, 403, 300, 292, 278, + 245, 261, 345, 288, 346, 262, 309, 308, 310, 0, + 193, 0, 381, 413, 434, 211, 0, 0, 393, 427, + 430, 0, 348, 212, 253, 244, 344, 251, 281, 426, + 428, 429, 210, 342, 259, 312, 206, 264, 377, 277, + 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 187, 200, + 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, + 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, + 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, + 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, + 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, + 374, 382, 385, 399, 400, 410, 420, 424, 258, 407, + 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, + 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, + 369, 388, 389, 390, 392, 303, 234, 321, 0, 1159, + 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, + 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, + 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, + 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, + 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, + 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, + 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 256, 0, 307, 0, + 0, 0, 421, 0, 0, 0, 0, 0, 0, 0, + 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, + 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, + 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, + 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, + 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, + 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, + 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, + 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, + 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, + 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, + 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, + 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, + 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, + 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, + 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, + 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, + 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, + 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, + 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, + 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, + 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, + 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, + 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, + 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, + 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, + 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, + 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, + 1134, 0, 0, 174, 175, 176, 0, 0, 0, 0, + 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, + 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, + 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, + 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, + 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, + 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, + 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, + 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, + 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, + 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, + 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, + 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, + 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, + 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, + 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, + 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, + 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, + 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, + 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, + 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, + 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, + 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, + 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, + 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, + 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, + 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, + 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, + 234, 1038, 0, 0, 0, 0, 0, 0, 321, 0, + 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, + 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, + 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, + 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, + 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, + 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, + 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, + 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, + 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, + 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, + 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, + 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, + 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, + 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, + 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, + 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, + 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, + 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, + 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, + 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, + 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, + 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, + 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, + 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, + 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, + 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, + 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, + 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, + 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, + 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, + 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, + 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, + 321, 0, 0, 0, 0, 0, 0, 0, 1029, 237, + 0, 0, 0, 0, 0, 280, 0, 0, 334, 0, + 370, 223, 289, 287, 396, 246, 240, 236, 222, 265, + 294, 332, 387, 326, 0, 284, 0, 0, 379, 306, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 270, 221, 192, 318, 380, + 249, 0, 0, 0, 174, 175, 176, 0, 0, 0, + 0, 0, 0, 0, 0, 213, 0, 219, 0, 0, + 0, 0, 233, 268, 239, 232, 394, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 256, + 0, 307, 0, 0, 0, 421, 0, 0, 0, 0, + 0, 0, 0, 0, 279, 0, 276, 188, 202, 0, + 0, 317, 355, 360, 0, 0, 0, 224, 0, 358, + 330, 409, 209, 247, 352, 335, 356, 0, 0, 357, + 285, 398, 347, 408, 422, 423, 231, 311, 415, 391, + 419, 431, 203, 228, 324, 384, 412, 376, 304, 395, + 275, 375, 254, 191, 283, 195, 386, 406, 214, 368, + 0, 0, 0, 197, 404, 383, 301, 272, 273, 196, + 0, 351, 235, 252, 226, 320, 401, 402, 225, 433, + 204, 418, 199, 205, 417, 313, 397, 405, 302, 293, + 198, 403, 300, 292, 278, 245, 261, 345, 288, 346, + 262, 309, 308, 310, 0, 193, 0, 381, 413, 434, + 211, 0, 0, 393, 427, 430, 0, 348, 212, 253, + 244, 344, 251, 281, 426, 428, 429, 210, 342, 259, + 312, 206, 264, 377, 277, 286, 0, 0, 329, 359, + 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 187, 200, 282, 0, 349, 250, 432, + 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 189, 190, 201, + 208, 217, 229, 242, 248, 257, 260, 263, 266, 267, + 269, 274, 291, 295, 296, 297, 298, 314, 315, 316, + 319, 322, 323, 325, 327, 328, 331, 337, 338, 339, + 340, 341, 343, 350, 354, 361, 362, 363, 364, 365, + 366, 367, 371, 372, 373, 374, 382, 385, 399, 400, + 410, 420, 424, 258, 407, 425, 0, 290, 0, 194, + 220, 207, 227, 241, 243, 271, 299, 305, 333, 336, + 255, 238, 218, 353, 216, 369, 388, 389, 390, 392, + 303, 234, 321, 0, 0, 0, 0, 0, 0, 0, + 0, 237, 0, 0, 0, 0, 0, 280, 0, 0, + 334, 0, 370, 223, 289, 287, 396, 246, 240, 236, + 222, 265, 294, 332, 387, 326, 0, 284, 0, 0, + 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 270, 221, 192, + 318, 380, 249, 0, 0, 0, 174, 175, 176, 0, + 902, 0, 0, 0, 0, 0, 0, 213, 0, 219, + 0, 0, 0, 0, 233, 268, 239, 232, 394, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 256, 0, 307, 0, 0, 0, 421, 0, 0, + 0, 0, 0, 0, 0, 0, 279, 0, 276, 188, + 202, 0, 0, 317, 355, 360, 0, 0, 0, 224, + 0, 358, 330, 409, 209, 247, 352, 335, 356, 0, + 0, 357, 285, 398, 347, 408, 422, 423, 231, 311, + 415, 391, 419, 431, 203, 228, 324, 384, 412, 376, + 304, 395, 275, 375, 254, 191, 283, 195, 386, 406, + 214, 368, 0, 0, 0, 197, 404, 383, 301, 272, + 273, 196, 0, 351, 235, 252, 226, 320, 401, 402, + 225, 433, 204, 418, 199, 205, 417, 313, 397, 405, + 302, 293, 198, 403, 300, 292, 278, 245, 261, 345, + 288, 346, 262, 309, 308, 310, 0, 193, 0, 381, + 413, 434, 211, 0, 0, 393, 427, 430, 0, 348, + 212, 253, 244, 344, 251, 281, 426, 428, 429, 210, + 342, 259, 312, 206, 264, 377, 277, 286, 0, 0, + 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 187, 200, 282, 0, 349, + 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 189, + 190, 201, 208, 217, 229, 242, 248, 257, 260, 263, + 266, 267, 269, 274, 291, 295, 296, 297, 298, 314, + 315, 316, 319, 322, 323, 325, 327, 328, 331, 337, + 338, 339, 340, 341, 343, 350, 354, 361, 362, 363, + 364, 365, 366, 367, 371, 372, 373, 374, 382, 385, + 399, 400, 410, 420, 424, 258, 407, 425, 0, 290, + 0, 194, 220, 207, 227, 241, 243, 271, 299, 305, + 333, 336, 255, 238, 218, 353, 216, 369, 388, 389, + 390, 392, 303, 234, 321, 0, 0, 0, 0, 0, + 0, 0, 0, 237, 0, 0, 0, 0, 0, 280, + 0, 0, 334, 0, 370, 223, 289, 287, 396, 246, + 240, 236, 222, 265, 294, 332, 387, 326, 0, 284, + 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, + 221, 192, 318, 380, 249, 0, 0, 0, 174, 175, + 176, 0, 0, 0, 0, 0, 0, 0, 0, 213, + 0, 219, 0, 0, 0, 0, 233, 268, 239, 232, + 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 187, 200, - 282, 0, 349, 250, 432, 416, 414, 0, 0, 230, + 0, 480, 0, 256, 0, 307, 0, 0, 0, 421, + 0, 0, 0, 0, 0, 0, 0, 0, 279, 0, + 276, 188, 202, 0, 0, 317, 355, 360, 0, 0, + 0, 224, 0, 358, 330, 409, 209, 247, 352, 335, + 356, 0, 0, 357, 285, 398, 347, 408, 422, 423, + 231, 311, 415, 391, 419, 431, 203, 228, 324, 384, + 412, 376, 304, 395, 275, 375, 254, 191, 283, 195, + 386, 406, 214, 368, 0, 0, 0, 197, 404, 383, + 301, 272, 273, 196, 0, 351, 235, 252, 226, 320, + 401, 402, 225, 433, 204, 418, 199, 205, 417, 313, + 397, 405, 302, 293, 198, 403, 300, 292, 278, 245, + 261, 345, 288, 346, 262, 309, 308, 310, 0, 193, + 0, 381, 413, 434, 211, 0, 0, 393, 427, 430, + 0, 348, 212, 253, 244, 344, 251, 281, 426, 428, + 429, 210, 342, 259, 312, 206, 264, 377, 277, 286, + 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 187, 200, 282, + 0, 349, 250, 432, 416, 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 189, 190, 201, 208, 217, 229, 242, 248, - 257, 260, 263, 266, 267, 269, 274, 291, 295, 296, - 297, 298, 314, 315, 316, 319, 322, 323, 325, 327, - 328, 331, 337, 338, 339, 340, 341, 343, 350, 354, - 361, 362, 363, 364, 365, 366, 367, 371, 372, 373, - 374, 382, 385, 399, 400, 410, 420, 424, 479, 407, - 425, 0, 290, 0, 194, 220, 207, 227, 241, 243, - 271, 299, 305, 333, 336, 255, 238, 218, 353, 216, - 369, 388, 389, 390, 392, 303, 234, 321, 0, 0, - 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, - 0, 0, 280, 0, 0, 334, 0, 370, 223, 289, - 287, 396, 246, 240, 236, 222, 265, 294, 332, 387, - 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 270, 221, 192, 318, 380, 249, 0, 0, - 0, 174, 175, 176, 0, 0, 0, 0, 0, 0, - 0, 0, 213, 0, 219, 0, 0, 0, 0, 233, - 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, + 0, 189, 190, 201, 208, 217, 229, 242, 248, 257, + 260, 263, 266, 267, 269, 274, 291, 295, 296, 297, + 298, 314, 315, 316, 319, 322, 323, 325, 327, 328, + 331, 337, 338, 339, 340, 341, 343, 350, 354, 361, + 362, 363, 364, 365, 366, 367, 371, 372, 373, 374, + 382, 385, 399, 400, 410, 420, 424, 479, 407, 425, + 0, 290, 0, 194, 220, 207, 227, 241, 243, 271, + 299, 305, 333, 336, 255, 238, 218, 353, 216, 369, + 388, 389, 390, 392, 303, 234, 321, 0, 0, 0, + 0, 0, 0, 0, 0, 237, 0, 0, 0, 0, + 0, 280, 0, 0, 334, 0, 370, 223, 289, 287, + 396, 246, 240, 236, 222, 265, 294, 332, 387, 326, + 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 270, 221, 192, 318, 380, 249, 0, 0, 0, + 174, 175, 176, 0, 0, 0, 0, 0, 0, 0, + 0, 213, 0, 219, 0, 0, 0, 0, 233, 268, + 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 256, 0, 307, 0, - 182, 0, 421, 0, 0, 0, 0, 0, 0, 0, - 0, 279, 0, 276, 188, 202, 0, 0, 317, 355, - 360, 0, 0, 0, 224, 0, 358, 330, 409, 209, - 247, 352, 335, 356, 0, 0, 357, 285, 398, 347, - 408, 422, 423, 231, 311, 415, 391, 419, 431, 203, - 228, 324, 384, 412, 376, 304, 395, 275, 375, 254, - 191, 283, 195, 386, 406, 214, 368, 0, 0, 0, - 197, 404, 383, 301, 272, 273, 196, 0, 351, 235, - 252, 226, 320, 401, 402, 225, 433, 204, 418, 199, - 205, 417, 313, 397, 405, 302, 293, 198, 403, 300, - 292, 278, 245, 261, 345, 288, 346, 262, 309, 308, - 310, 0, 193, 0, 381, 413, 434, 211, 0, 0, - 393, 427, 430, 0, 348, 212, 253, 244, 344, 251, - 281, 426, 428, 429, 210, 342, 259, 312, 206, 264, - 377, 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 256, 0, 307, 0, 182, + 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, + 279, 0, 276, 188, 202, 0, 0, 317, 355, 360, + 0, 0, 0, 224, 0, 358, 330, 409, 209, 247, + 352, 335, 356, 0, 0, 357, 285, 398, 347, 408, + 422, 423, 231, 311, 415, 391, 419, 431, 203, 228, + 324, 384, 412, 376, 304, 395, 275, 375, 254, 191, + 283, 195, 386, 406, 214, 368, 0, 0, 0, 197, + 404, 383, 301, 272, 273, 196, 0, 351, 235, 252, + 226, 320, 401, 402, 225, 433, 204, 418, 199, 205, + 417, 313, 397, 405, 302, 293, 198, 403, 300, 292, + 278, 245, 261, 345, 288, 346, 262, 309, 308, 310, + 0, 193, 0, 381, 413, 434, 211, 0, 0, 393, + 427, 430, 0, 348, 212, 253, 244, 344, 251, 281, + 426, 428, 429, 210, 342, 259, 312, 206, 264, 377, + 277, 286, 0, 0, 329, 359, 215, 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 187, 200, 282, 0, 349, 250, 432, 416, 414, 0, - 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 187, + 200, 282, 0, 349, 250, 432, 416, 414, 0, 0, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 189, 190, 201, 208, 217, 229, - 242, 248, 257, 260, 263, 266, 267, 269, 274, 291, - 295, 296, 297, 298, 314, 315, 316, 319, 322, 323, - 325, 327, 328, 331, 337, 338, 339, 340, 341, 343, - 350, 354, 361, 362, 363, 364, 365, 366, 367, 371, - 372, 373, 374, 382, 385, 399, 400, 410, 420, 424, - 258, 407, 425, 0, 290, 0, 194, 220, 207, 227, - 241, 243, 271, 299, 305, 333, 336, 255, 238, 218, - 353, 216, 369, 388, 389, 390, 392, 303, 234, 321, - 0, 0, 0, 0, 0, 0, 0, 0, 237, 0, - 0, 0, 0, 0, 280, 0, 0, 334, 0, 370, - 223, 289, 287, 396, 246, 240, 236, 222, 265, 294, - 332, 387, 326, 0, 284, 0, 0, 379, 306, 0, + 0, 0, 0, 189, 190, 201, 208, 217, 229, 242, + 248, 257, 260, 263, 266, 267, 269, 274, 291, 295, + 296, 297, 298, 314, 315, 316, 319, 322, 323, 325, + 327, 328, 331, 337, 338, 339, 340, 341, 343, 350, + 354, 361, 362, 363, 364, 365, 366, 367, 371, 372, + 373, 374, 382, 385, 399, 400, 410, 420, 424, 258, + 407, 425, 0, 290, 0, 194, 220, 207, 227, 241, + 243, 271, 299, 305, 333, 336, 255, 238, 218, 353, + 216, 369, 388, 389, 390, 392, 303, 234, 321, 0, + 0, 0, 0, 0, 0, 0, 0, 237, 0, 0, + 0, 0, 0, 280, 0, 0, 334, 0, 370, 223, + 289, 287, 396, 246, 240, 236, 222, 265, 294, 332, + 387, 326, 0, 284, 0, 0, 379, 306, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 270, 221, 192, 318, 380, 249, - 0, 0, 0, 174, 175, 176, 0, 0, 0, 0, - 0, 0, 0, 0, 213, 0, 219, 0, 0, 0, - 0, 233, 268, 239, 232, 394, 0, 0, 0, 0, + 0, 0, 0, 270, 221, 192, 318, 380, 249, 0, + 0, 0, 174, 175, 176, 0, 0, 0, 0, 0, + 0, 0, 0, 213, 0, 219, 0, 0, 0, 0, + 233, 268, 239, 232, 394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 256, 0, - 307, 0, 0, 0, 421, 0, 0, 0, 0, 0, - 0, 0, 0, 279, 0, 276, 188, 202, 0, 0, - 317, 355, 360, 0, 0, 0, 224, 0, 358, 330, - 409, 209, 247, 352, 335, 356, 0, 0, 357, 285, - 398, 347, 408, 422, 423, 231, 311, 415, 391, 419, - 431, 203, 228, 324, 384, 412, 376, 304, 395, 275, - 375, 254, 191, 283, 195, 386, 406, 214, 368, 0, - 0, 0, 197, 404, 383, 301, 272, 273, 196, 0, - 351, 235, 252, 226, 320, 401, 402, 225, 433, 204, - 418, 199, 205, 417, 313, 397, 405, 302, 293, 198, - 403, 300, 292, 278, 245, 261, 345, 288, 346, 262, - 309, 308, 310, 0, 193, 0, 381, 413, 434, 211, - 0, 0, 393, 427, 430, 0, 348, 212, 253, 244, - 344, 251, 281, 426, 428, 429, 210, 342, 259, 312, - 206, 264, 377, 277, 286, 0, 0, 329, 359, 215, - 411, 378, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 256, 0, 307, + 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, + 0, 0, 279, 0, 276, 188, 202, 0, 0, 317, + 355, 360, 0, 0, 0, 224, 0, 358, 330, 409, + 209, 247, 352, 335, 356, 0, 0, 357, 285, 398, + 347, 408, 422, 423, 231, 311, 415, 391, 419, 431, + 203, 228, 324, 384, 412, 376, 304, 395, 275, 375, + 254, 191, 283, 195, 386, 406, 214, 368, 0, 0, + 0, 197, 404, 383, 301, 272, 273, 196, 0, 351, + 235, 252, 226, 320, 401, 402, 225, 433, 204, 418, + 199, 205, 417, 313, 397, 405, 302, 293, 198, 403, + 300, 292, 278, 245, 261, 345, 288, 346, 262, 309, + 308, 310, 0, 193, 0, 381, 413, 434, 211, 0, + 0, 393, 427, 430, 0, 348, 212, 253, 244, 344, + 251, 281, 426, 428, 429, 210, 342, 259, 312, 206, + 264, 377, 277, 286, 0, 0, 329, 359, 215, 411, + 378, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 187, 200, 282, 0, 349, 250, 432, 416, - 414, 0, 0, 230, 0, 0, 0, 0, 0, 0, + 0, 187, 200, 282, 0, 349, 250, 432, 416, 414, + 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 189, 190, 201, 208, - 217, 229, 242, 248, 257, 260, 263, 266, 267, 269, - 274, 291, 295, 296, 297, 298, 314, 315, 316, 319, - 322, 323, 325, 327, 328, 331, 337, 338, 339, 340, - 341, 343, 350, 354, 361, 362, 363, 364, 365, 366, - 367, 371, 372, 373, 374, 382, 385, 399, 400, 410, - 420, 424, 258, 407, 425, 0, 290, 0, 194, 220, - 207, 227, 241, 243, 271, 299, 305, 333, 336, 255, - 238, 218, 353, 216, 369, 388, 389, 390, 392, 303, - 234, + 0, 0, 0, 0, 0, 189, 190, 201, 208, 217, + 229, 242, 248, 257, 260, 263, 266, 267, 269, 274, + 291, 295, 296, 297, 298, 314, 315, 316, 319, 322, + 323, 325, 327, 328, 331, 337, 338, 339, 340, 341, + 343, 350, 354, 361, 362, 363, 364, 365, 366, 367, + 371, 372, 373, 374, 382, 385, 399, 400, 410, 420, + 424, 258, 407, 425, 0, 290, 0, 194, 220, 207, + 227, 241, 243, 271, 299, 305, 333, 336, 255, 238, + 218, 353, 216, 369, 388, 389, 390, 392, 303, 234, } var yyPact = [...]int{ - 286, -1000, -331, 1566, -1000, -1000, -1000, -1000, -1000, -1000, + 3884, -1000, -328, 1476, -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, 1521, 1158, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 624, 1202, 102, 1429, 3586, 206, 925, 387, 79, 25498, - 380, 110, 25930, -1000, 90, -1000, 74, 25930, 86, 25066, - -1000, -1000, -1000, 12073, 1380, -4, -5, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 1178, 1483, 1490, 1516, 1020, - 1499, -1000, 10332, 10332, 337, 337, 337, 8604, -1000, -1000, - 15974, 25930, 25930, 1215, 325, 376, 325, -126, -1000, -1000, - -1000, -1000, -1000, -1000, 1429, -1000, -1000, 124, -1000, 222, - 1154, -1000, 1142, -1000, 355, 393, 255, 323, 291, 252, - 246, 240, 238, 235, 234, 233, 230, 261, -1000, 509, - 509, -193, -195, 1877, 314, 314, 314, 358, 1392, 1389, - -1000, 512, -1000, 509, 509, 119, 509, 509, 509, 509, - 176, 175, 509, 509, 509, 509, 509, 509, 509, 509, - 509, 509, 509, 509, 509, 509, 509, 25930, -1000, 136, - 496, 559, 1429, 167, -1000, -1000, -1000, 25930, 319, 925, - 319, 319, 25930, -1000, 438, -1000, -1000, -1000, -1000, -1000, + -1000, 1440, 1138, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 526, 1149, 205, 1349, 3394, 131, 925, 364, 101, 25457, + 361, 2020, 25889, -1000, 77, -1000, 63, 25889, 69, 25025, + -1000, -1000, -1000, 12032, 1313, -29, -37, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 1167, 1412, 1417, 1438, 1008, + 1474, -1000, 10291, 10291, 306, 306, 306, 8563, -1000, -1000, + 15933, 25889, 25889, 1161, 299, 337, 299, -138, -1000, -1000, + -1000, -1000, -1000, -1000, 1349, -1000, -1000, 129, -1000, 222, + 1105, -1000, 1102, -1000, 438, 359, 215, 288, 287, 214, + 212, 210, 206, 204, 200, 199, 198, 238, -1000, 494, + 494, -191, -192, 2360, 295, 295, 295, 324, 1326, 1325, + -1000, 544, -1000, 494, 494, 113, 494, 494, 494, 494, + 178, 177, 494, 494, 494, 494, 494, 494, 494, 494, + 494, 494, 494, 494, 494, 494, 494, 25889, -1000, 130, + 491, 530, 1349, 155, -1000, -1000, -1000, 25889, 297, 925, + 297, 297, 25889, -1000, 408, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -3830,23 +3825,23 @@ var yyPact = [...]int{ -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, -1000, 25930, 585, 585, 585, 585, - 585, 585, 63, -1000, 50, 164, 161, 146, 20, 925, - 196, -1000, 431, -1000, 138, 42, -1000, 585, 5928, 5928, - 5928, -1000, 1403, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 357, -1000, -1000, -1000, -1000, 25930, 24634, 180, 555, - -1000, -1000, -1000, -1000, 1082, 695, -1000, 12073, 1203, 1170, - 1170, -1000, -1000, 416, -1000, -1000, 13369, 13369, 13369, 13369, - 13369, 13369, 13369, 13369, 13369, 13369, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 25889, 639, 639, 639, 639, + 639, 639, 49, -1000, 48, 171, 166, 152, 22, 925, + 112, -1000, 423, -1000, 143, 74, -1000, 639, 5887, 5887, + 5887, -1000, 1333, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 323, -1000, -1000, -1000, -1000, 25889, 24593, 180, 529, + -1000, -1000, -1000, -1000, 1030, 468, -1000, 12032, 3489, 1108, + 1108, -1000, -1000, 386, -1000, -1000, 13328, 13328, 13328, 13328, + 13328, 13328, 13328, 13328, 13328, 13328, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 1170, 436, -1000, 11641, 1170, 1170, 1170, 1170, 1170, 1170, - 1170, 1170, 12073, 1170, 1170, 1170, 1170, 1170, 1170, 1170, - 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, 1170, -1000, - -1000, -1000, 25930, -1000, 1521, -1000, 1158, -1000, -1000, -1000, - 1407, 12073, 12073, 1521, -1000, 1321, 10332, -1000, -1000, 1471, - -1000, -1000, -1000, -1000, 666, 1545, -1000, 14665, 433, 1536, - 24202, -1000, 18579, 23770, 1138, 8158, -53, -1000, -1000, -1000, - 545, 17715, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + 1108, 406, -1000, 11600, 1108, 1108, 1108, 1108, 1108, 1108, + 1108, 1108, 12032, 1108, 1108, 1108, 1108, 1108, 1108, 1108, + 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, + -1000, -1000, -1000, 25889, -1000, 1440, -1000, 1138, -1000, -1000, + -1000, 1350, 12032, 12032, 1440, -1000, 1256, 10291, -1000, -1000, + 1339, -1000, -1000, -1000, -1000, 677, 1455, -1000, 14624, 404, + 1454, 24161, -1000, 18538, 23729, 1101, 8117, -70, -1000, -1000, + -1000, 509, 17674, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, @@ -3860,179 +3855,179 @@ 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, - 1403, 1070, 25930, -1000, -1000, 2553, 925, -1000, 1201, -1000, - 1068, -1000, 1174, 136, 25930, 579, 925, 925, -1000, -1000, - -1000, 509, 509, 260, 3586, 4039, -1000, -1000, -1000, 23331, - 1200, 925, -1000, 1197, -1000, 1449, 329, 502, 502, 925, - -1000, -1000, 25930, 925, 1447, 1444, 25930, 25930, -1000, 22899, - -1000, 22467, 22035, 849, 25930, 21603, 21171, 20739, 20307, 19875, - -1000, 1274, -1000, 1169, -1000, -1000, -1000, 25930, 25930, 25930, - 4, -1000, -1000, 25930, 925, -1000, -1000, 848, 846, 509, - 509, 830, 930, 928, 927, 509, 509, 829, 924, 919, - 142, 811, 775, 773, 896, 918, 105, 875, 873, 764, - 25930, 1193, -1000, 129, 521, 183, 220, 193, 25930, 135, - 1429, 1379, 1137, 356, 25930, 1464, 1247, 25930, 925, -1000, - 7266, -1000, -1000, 909, 12073, -1000, -1000, -1000, -1000, -1000, - 585, 25930, 585, 25930, 585, 585, 585, 585, 619, 623, - 619, -1000, -1000, -1000, -1000, 5928, 5928, 25930, 5928, 5928, - 25930, 5928, 5928, 623, -1000, -1000, -1000, 479, -1000, 1245, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, 81, -1000, -1000, - -1000, -1000, -1000, 1566, -1000, -1000, -1000, -124, 12073, 12073, - 12073, 12073, 713, 500, 13369, 681, 614, 13369, 13369, 13369, - 13369, 13369, 13369, 13369, 13369, 13369, 13369, 13369, 13369, 13369, - 13369, 13369, 608, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 925, -1000, 1564, 1179, 1179, 449, 449, 449, 449, - 449, 449, 449, 449, 449, 13801, 9036, 7266, 1020, 1053, - 1521, 10332, 10332, 12073, 12073, 11196, 10764, 10332, 1414, 548, - 695, 25930, -1000, -1000, 12937, -1000, -1000, -1000, -1000, -1000, - 938, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 25930, 25930, - 10332, 10332, 10332, 10332, 10332, -1000, 1135, -1000, -172, 15542, - 1490, 1020, 1471, 1454, 1557, 470, 736, 1122, -1000, 750, - 1490, 17283, 1089, -1000, 1471, -1000, -1000, -1000, 25930, -1000, - -1000, 19443, -1000, -1000, 6820, 25930, 229, 25930, -1000, 1129, - 1293, -1000, -1000, -1000, 1480, 16851, 25930, 1067, 1057, -1000, - -1000, 430, 7712, -53, -1000, 7712, 1099, -1000, -72, -38, - 9468, 447, -1000, -1000, -1000, 1877, 14233, 1001, 634, 10, - -1000, -1000, -1000, 1174, -1000, 1174, 1174, 1174, 1174, 4, - 4, 4, 4, -1000, -1000, -1000, -1000, -1000, 1192, 1184, - -1000, 1174, 1174, 1174, 1174, -1000, -1000, -1000, -1000, -1000, + -1000, 1333, 1061, 25889, -1000, -1000, 3547, 925, -1000, 1145, + -1000, 1055, -1000, 1114, 130, 25889, 579, 925, 925, -1000, + -1000, -1000, 494, 494, 229, 3394, 267, -1000, -1000, -1000, + 23290, 1144, 925, -1000, 1140, -1000, 1366, 294, 487, 487, + 925, -1000, -1000, 25889, 925, 1365, 1359, 25889, 25889, -1000, + 22858, -1000, 22426, 21994, 800, 25889, 21562, 21130, 20698, 20266, + 19834, -1000, 1218, -1000, 1189, -1000, -1000, -1000, 25889, 25889, + 25889, -12, -1000, -1000, 25889, 925, -1000, -1000, 787, 767, + 494, 494, 765, 896, 895, 891, 494, 494, 763, 890, + 916, 132, 760, 759, 756, 808, 887, 103, 784, 742, + 751, 25889, 1137, -1000, 104, 505, 182, 225, 174, 25889, + 102, 1349, 1310, 1098, 311, 25889, 1397, 1224, 25889, 925, + -1000, 7225, -1000, -1000, 886, 12032, -1000, -1000, -1000, -1000, + -1000, 639, 25889, 639, 25889, 639, 639, 639, 639, 557, + 583, 557, -1000, -1000, -1000, -1000, 5887, 5887, 25889, 5887, + 5887, 25889, 5887, 5887, 583, -1000, -1000, -1000, 453, -1000, + 1222, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 67, -1000, + -1000, -1000, -1000, -1000, 1476, -1000, -1000, -1000, -123, 12032, + 12032, 12032, 12032, 852, 464, 13328, 753, 669, 13328, 13328, + 13328, 13328, 13328, 13328, 13328, 13328, 13328, 13328, 13328, 13328, + 13328, 13328, 13328, 634, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 925, -1000, 1470, 1015, 1015, 407, 407, 407, + 407, 407, 407, 407, 407, 407, 13760, 8995, 7225, 1008, + 1043, 1440, 10291, 10291, 12032, 12032, 11155, 10723, 10291, 1336, + 553, 468, 25889, -1000, 905, -1000, -1000, 12896, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1180, 1180, 1180, 1175, 1175, 298, -1000, 12073, - 94, 25930, 1476, 752, 129, -1000, 1462, 1230, -1000, 914, - 898, -1000, 1116, -1000, -1000, 1509, -1000, -1000, 462, 627, - 621, 458, 25930, 107, 224, -1000, 289, -1000, 25930, 1177, - 1437, 502, 925, -1000, 925, -1000, -1000, -1000, -1000, 428, - -1000, -1000, 925, 1115, -1000, 1114, 711, 617, 690, 604, - 1115, -1000, -1000, -160, 1115, -1000, 1115, -1000, 1115, -1000, - 1115, -1000, 1115, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, 519, 25930, 107, 608, -1000, 339, -1000, -1000, 608, - 608, -1000, -1000, -1000, -1000, 906, 905, -1000, -1000, -1000, + 25889, 25889, 10291, 10291, 10291, 10291, 10291, -1000, 1091, -1000, + -168, 15501, 1417, 1008, 1339, 1376, 1464, 444, 899, 1088, + -1000, 809, 1417, 17242, 1077, -1000, 1339, -1000, -1000, -1000, + 25889, -1000, -1000, 19402, -1000, -1000, 6779, 25889, 197, 25889, + -1000, 1099, 1193, -1000, -1000, -1000, 1406, 16810, 25889, 1084, + 1075, -1000, -1000, 403, 7671, -70, -1000, 7671, 1071, -1000, + -96, -76, 9427, 385, -1000, -1000, -1000, 2360, 14192, 947, + 611, -11, -1000, -1000, -1000, 1114, -1000, 1114, 1114, 1114, + 1114, -12, -12, -12, -12, -1000, -1000, -1000, -1000, -1000, + 1131, 1121, -1000, 1114, 1114, 1114, 1114, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1119, 1119, 1119, 1115, 1115, 282, + -1000, 12032, 81, 25889, 1387, 748, 104, -1000, 1381, 1198, + -1000, 884, 875, -1000, 1087, -1000, -1000, 1437, -1000, -1000, + 462, 632, 630, 458, 25889, 94, 194, -1000, 273, -1000, + 25889, 1118, 1358, 487, 925, -1000, 925, -1000, -1000, -1000, + -1000, 402, -1000, -1000, 925, 1085, -1000, 1093, 687, 617, + 664, 601, 1085, -1000, -1000, -172, 1085, -1000, 1085, -1000, + 1085, -1000, 1085, -1000, 1085, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, 490, 25889, 94, 634, -1000, 309, -1000, + -1000, 634, 634, -1000, -1000, -1000, -1000, 878, 869, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -316, 25930, 364, 106, 115, 25930, 25930, - 25930, 25930, 25930, 407, -1000, -1000, -1000, 173, 25930, 25930, - 383, -1000, 25930, 377, -1000, -1000, -1000, -1000, -1000, -1000, - 695, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 585, - 25930, 25930, 25930, -1000, -1000, 585, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 25930, -1000, 899, 25930, 25930, -1000, - -1000, -1000, -1000, -1000, 695, 500, 563, 630, -1000, -1000, - 817, -1000, -1000, 2268, -1000, -1000, -1000, -1000, 681, 13369, - 13369, 13369, 481, 2268, 2159, 1543, 2060, 449, 544, 544, - 454, 454, 454, 454, 454, 564, 564, -1000, -1000, -1000, - -1000, 938, -1000, -1000, -1000, 938, 10332, 10332, 1105, 1170, - 427, -1000, 1178, -1000, -1000, 1490, 1000, 1000, 691, 852, - 557, 1534, 1000, 539, 1529, 1000, 1000, 10332, -1000, -1000, - 643, -1000, 12073, 938, -1000, 759, 1101, 1100, 1000, 938, - 938, 1000, 1000, 25930, -1000, -289, -1000, -109, 437, 1170, - -1000, 19011, -1000, -1000, 1407, -1000, -1000, 1365, -1000, 1322, - 12073, 12073, 12073, -1000, -1000, -1000, 1407, 1498, -1000, 1340, - 1339, 1526, 10332, 18579, 1471, -1000, -1000, -1000, 426, 1526, - 1079, 1170, -1000, 25930, 18579, 18579, 18579, 18579, 18579, -1000, - 1291, 1290, -1000, 1318, 1301, 1305, 25930, -1000, 1037, 1020, - 16851, 229, 1063, 18579, 25930, -1000, -1000, 18579, 25930, 6374, - -1000, 1099, -53, -54, -1000, -1000, -1000, -1000, 695, -1000, - 885, -1000, 283, -1000, 311, -1000, -1000, -1000, -1000, 1428, - -1000, 647, 5, -1000, -1000, 4, 4, -1000, -1000, 447, - 651, 447, 447, 447, 892, 892, -1000, -1000, -1000, -1000, - -1000, 737, -1000, -1000, -1000, 735, -1000, -1000, 660, 1268, - 94, -1000, -1000, 509, 886, 1385, 25930, -1000, -1000, 976, - 360, -1000, 1244, -1000, -1000, -1000, -1000, -1000, 3274, 25930, - 1032, -1000, 103, 25930, 973, 25930, -1000, 1027, 25930, -1000, - 925, -1000, -1000, 7266, -1000, 25930, 1170, -1000, -1000, -1000, - -1000, 378, 1415, 1408, 107, 103, 447, 925, -1000, -1000, - -1000, -1000, -1000, -320, 1022, 25930, 130, -1000, 1176, 934, - -1000, 1222, -1000, -1000, -1000, -1000, 87, 182, 169, 330, - -1000, -1000, -1000, -1000, 5928, 25930, -1000, -1000, -1000, -1000, - 619, -1000, 619, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 481, 2268, 815, -1000, 13369, 13369, -1000, -1000, 1000, 1000, - 10332, 7266, 1521, 1407, -1000, -1000, 171, 608, 171, 13369, - 13369, -1000, 13369, 13369, -1000, -153, 1141, 568, -1000, 12073, - 805, -1000, -1000, 13369, 13369, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, -1000, -1000, 375, 369, 367, 25930, -1000, -1000, - 845, 877, 1319, 695, 695, -1000, -1000, 25930, -1000, -1000, - -1000, -1000, 1524, 12073, -1000, 1098, -1000, 5482, 1490, 1243, - 25930, 1170, 1566, 15110, 25930, 1086, -1000, 513, 1293, 1233, - 1241, 1224, -1000, -1000, -1000, -1000, 1289, -1000, 1281, -1000, - -1000, -1000, -1000, -1000, 1020, 1526, 18579, 1034, -1000, 1034, - -1000, 425, -1000, -1000, -1000, -81, -65, -1000, -1000, -1000, - 1877, -1000, -1000, 1238, 13369, -1000, -1000, -1000, 447, 447, - -1000, -1000, -1000, -1000, -1000, -1000, 996, -1000, 994, 1097, - 986, 34, -1000, 1207, 1400, 509, 509, -1000, 725, -1000, - 925, -1000, -1000, 25930, 25930, 1508, 1096, -1000, 25930, -1000, - -1000, 25930, -1000, -1000, 1333, 94, 984, -1000, -1000, -1000, - 224, 25930, -1000, 1179, 103, -1000, -1000, -1000, -1000, -1000, - -1000, 1172, -1000, -1000, -1000, 960, -1000, -161, 925, 25930, - 25930, 25930, -1000, 25930, -1000, -1000, 585, 585, -1000, 13369, - 2268, 2268, -1000, -1000, 938, -1000, 1490, -1000, 938, 1174, - 1174, -1000, 1174, 1175, -1000, 1174, 66, 1174, 54, 938, - 938, 2198, 2144, 2046, 1965, 1170, -146, -1000, 695, 12073, - 1684, 958, 1170, 1170, 1170, 979, 868, 4, -1000, -1000, - -1000, 1500, 1507, 695, -1000, -1000, -1000, 1416, 1050, 1080, - -1000, -1000, 9900, 981, 1330, 424, 979, 1521, 25930, 12073, - -1000, -1000, 12073, 1173, -1000, 12073, -1000, -1000, -1000, 1521, - 1521, 1034, -1000, -1000, 461, -1000, -1000, -1000, -1000, 15, - 1556, 2268, -1000, -1000, 4, 854, 4, 708, -1000, 703, - -1000, -1000, -232, -1000, -1000, 1094, 1272, -1000, -1000, 1172, - -1000, 25930, 25930, -1000, -1000, 184, -1000, 276, 972, -1000, - -190, -1000, -1000, 1475, 25930, -1000, -1000, 7266, -1000, -1000, - 1171, 1225, -1000, -1000, -1000, -1000, 2268, -1000, 1407, -1000, - -1000, 201, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, - 13369, 13369, 13369, 13369, 13369, 1490, 853, 695, 13369, 13369, - 18147, 25930, 25930, 16406, 4, -12, -1000, 12073, 12073, 1436, - -1000, 1170, -1000, 1148, 25930, 1170, 25930, -1000, 1490, -1000, - 695, 695, 25930, 695, 1490, -1000, 483, -1000, -165, 447, - -1000, 447, 953, 947, -1000, -1000, -1000, -1000, -1000, -1000, - -1000, -1000, 1472, 1096, -1000, 213, 25930, -1000, 224, -1000, - -197, -198, 1158, 970, 1087, -1000, 488, 25930, 25930, -1000, - -1000, -1000, 759, 759, 759, 759, 202, 938, -1000, 759, - 759, 963, -1000, 963, 963, 437, -284, -1000, 1376, 1373, - 695, 1082, 1555, -1000, 1170, 1566, 406, 1080, -1000, -1000, - 952, -1000, 658, 1433, -1000, 1431, -1000, -1000, -1000, -1000, - -1000, 1158, 1170, 1095, -1000, -1000, -1000, 165, -1000, 7266, - 5036, 950, -1000, -1000, -1000, -1000, -1000, 938, 112, -164, - -1000, -1000, -1000, -1000, -1000, -1000, -1000, -12, 262, -1000, - 1345, 1343, 1506, 25930, 1080, 25930, -1000, -1000, 760, -1000, - -1000, 165, 12505, 25930, -1000, -75, -1000, -1000, -1000, -1000, - -1000, 1222, -1000, 1315, -157, -175, 1349, 1351, 1351, 1373, - 1505, 1360, 1357, -1000, 751, 1077, -1000, -1000, -1000, 759, - 938, 942, 293, -1000, -1000, -161, -1000, 1302, -1000, 1347, - 838, -1000, -1000, -1000, -1000, 734, -1000, 1502, 1496, -1000, - -1000, -1000, 1237, 132, -1000, -162, -1000, 765, -1000, -1000, - -1000, 692, 682, 1236, -1000, 1540, -1000, -170, -1000, -1000, - -1000, -1000, -1000, 1554, 465, 465, -180, -1000, -1000, -1000, - 290, 733, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -317, 25889, 328, 85, 115, + 25889, 25889, 25889, 25889, 25889, 378, -1000, -1000, -1000, 159, + 25889, 25889, 357, -1000, 25889, 338, -1000, -1000, -1000, -1000, + -1000, -1000, 468, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, 639, 25889, 25889, 25889, -1000, -1000, 639, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 25889, -1000, 868, 25889, + 25889, -1000, -1000, -1000, -1000, -1000, 468, 464, 531, 495, + -1000, -1000, 725, -1000, -1000, 2766, -1000, -1000, -1000, -1000, + 753, 13328, 13328, 13328, 375, 2766, 2445, 620, 793, 407, + 605, 605, 422, 422, 422, 422, 422, 594, 594, -1000, + -1000, -1000, -1000, 905, -1000, -1000, -1000, 905, 10291, 10291, + 1083, 1108, 401, -1000, 1167, -1000, -1000, 1417, 1010, 1010, + 692, 846, 565, 1453, 1010, 536, 1452, 1010, 1010, 10291, + -1000, -1000, 556, -1000, 12032, 905, -1000, 1206, 1082, 1072, + 1010, 905, 905, 1010, 1010, 25889, -1000, -291, -1000, -121, + 400, 1108, -1000, 18970, -1000, -1000, 1350, -1000, -1000, 1308, + -1000, 1253, 12032, 12032, 12032, -1000, -1000, -1000, 1350, 1426, + -1000, 1269, 1266, 1447, 10291, 18538, 1339, -1000, -1000, -1000, + 398, 1447, 1123, 1108, -1000, 25889, 18538, 18538, 18538, 18538, + 18538, -1000, 1239, 1236, -1000, 1237, 1235, 1243, 25889, -1000, + 1037, 1008, 16810, 197, 960, 18538, 25889, -1000, -1000, 18538, + 25889, 6333, -1000, 1071, -70, -38, -1000, -1000, -1000, -1000, + 468, -1000, 773, -1000, 2337, -1000, 275, -1000, -1000, -1000, + -1000, 1348, -1000, 670, 6, -1000, -1000, -12, -12, -1000, + -1000, 385, 475, 385, 385, 385, 859, 859, -1000, -1000, + -1000, -1000, -1000, 743, -1000, -1000, -1000, 737, -1000, -1000, + 735, 1207, 81, -1000, -1000, 494, 850, 1320, 25889, -1000, + -1000, 940, 326, -1000, 1219, -1000, -1000, -1000, -1000, -1000, + 245, 25889, 1034, -1000, 84, 25889, 933, 25889, -1000, 1016, + 25889, -1000, 925, -1000, -1000, 7225, -1000, 25889, 1108, -1000, + -1000, -1000, -1000, 339, 1341, 1335, 94, 84, 385, 925, + -1000, -1000, -1000, -1000, -1000, -320, 1012, 25889, 139, -1000, + 1116, 902, -1000, 1176, -1000, -1000, -1000, -1000, 83, 181, + 153, 308, -1000, -1000, -1000, -1000, 5887, 25889, -1000, -1000, + -1000, -1000, 557, -1000, 557, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 375, 2766, 2198, -1000, 13328, 13328, -1000, -1000, + 1010, 1010, 10291, 7225, 1440, 1350, -1000, -1000, 192, 634, + 192, 13328, 13328, -1000, 13328, 13328, -1000, -155, 1097, 537, + -1000, 12032, 705, -1000, -1000, 13328, 13328, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, 335, 332, 331, 25889, + -1000, -1000, 789, 833, 1248, 468, 468, -1000, -1000, 25889, + -1000, -1000, -1000, -1000, 1445, 12032, -1000, 1068, -1000, 5441, + 1417, 1217, 25889, 1108, 1476, 15069, 25889, 1057, -1000, 503, + 1193, 1197, 1215, 1614, -1000, -1000, -1000, -1000, 1228, -1000, + 1216, -1000, -1000, -1000, -1000, -1000, 1008, 1447, 18538, 1018, + -1000, 1018, -1000, 391, -1000, -1000, -1000, -106, -117, -1000, + -1000, -1000, 2360, -1000, -1000, 1212, 13328, -1000, -1000, -1000, + 385, 385, -1000, -1000, -1000, -1000, -1000, -1000, 999, -1000, + 996, 1059, 994, 34, -1000, 1160, 1331, 494, 494, -1000, + 732, -1000, 925, -1000, -1000, 25889, 25889, 1436, 1053, -1000, + 25889, -1000, -1000, 25889, -1000, -1000, 1265, 81, 985, -1000, + -1000, -1000, 194, 25889, -1000, 1015, 84, -1000, -1000, -1000, + -1000, -1000, -1000, 1110, -1000, -1000, -1000, 922, -1000, -173, + 925, 25889, 25889, 25889, -1000, 25889, -1000, -1000, 639, 639, + -1000, 13328, 2766, 2766, -1000, -1000, 905, -1000, 1417, -1000, + 905, 1114, 1114, -1000, 1114, 1115, -1000, 1114, 54, 1114, + 53, 905, 905, 2680, 2427, 2273, 2147, 1108, -149, -1000, + 468, 12032, 2055, 1685, 1108, 1108, 1108, 981, 832, -12, + -1000, -1000, -1000, 1442, 1435, 468, -1000, -1000, -1000, 1369, + 979, 987, -1000, -1000, 9859, 983, 1260, 384, 981, 1440, + 25889, 12032, -1000, -1000, 12032, 1111, -1000, 12032, -1000, -1000, + -1000, 1440, 1440, 1018, -1000, -1000, 431, -1000, -1000, -1000, + -1000, 13, 1463, 2766, -1000, -1000, -12, 827, -12, 715, + -1000, 697, -1000, -1000, -230, -1000, -1000, 1174, 1200, -1000, + -1000, 1110, -1000, 25889, 25889, -1000, -1000, 190, -1000, 253, + 975, -1000, -189, -1000, -1000, 1402, 25889, -1000, -1000, 7225, + -1000, -1000, 1109, 1181, -1000, -1000, -1000, -1000, 2766, -1000, + 1350, -1000, -1000, 196, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, 13328, 13328, 13328, 13328, 13328, 1417, 826, 468, + 13328, 13328, 18106, 25889, 25889, 16365, -12, -19, -1000, 12032, + 12032, 1356, -1000, 1108, -1000, 1079, 25889, 1108, 25889, -1000, + 1417, -1000, 468, 468, 25889, 468, 1417, -1000, 446, -1000, + -78, 385, -1000, 385, 915, 908, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 1399, 1053, -1000, 186, 25889, -1000, + 194, -1000, -194, -195, 1138, 965, 1047, -1000, 482, 25889, + 25889, -1000, -1000, -1000, 1206, 1206, 1206, 1206, 195, 905, + -1000, 1206, 1206, 954, -1000, 954, 954, 400, -281, -1000, + 1309, 1306, 468, 1030, 1462, -1000, 1108, 1476, 382, 987, + -1000, -1000, 938, -1000, 672, 1354, -1000, 1340, -1000, -1000, + -1000, -1000, -1000, 1138, 1108, 1080, -1000, -1000, -1000, 151, + -1000, 7225, 4995, 930, -1000, -1000, -1000, -1000, -1000, 905, + 98, -177, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -19, + 242, -1000, 1273, 1271, 1431, 25889, 987, 25889, -1000, -1000, + 819, -1000, -1000, 151, 12464, 25889, -1000, -72, -1000, -1000, + -1000, -1000, -1000, 1176, -1000, 1221, -170, -186, 1277, 1280, + 1280, 1306, 1430, 1303, 1284, -1000, 817, 963, -1000, -1000, + -1000, 1206, 905, 912, 269, -1000, -1000, -173, -1000, 1214, + -1000, 1275, 704, -1000, -1000, -1000, -1000, 810, -1000, 1428, + 1423, -1000, -1000, -1000, 1210, 127, -1000, -175, -1000, 702, + -1000, -1000, -1000, 806, 774, 1204, -1000, 1451, -1000, -184, + -1000, -1000, -1000, -1000, -1000, 1460, 414, 414, -187, -1000, + -1000, -1000, 278, 730, -1000, -1000, -1000, -1000, -1000, } var yyPgo = [...]int{ - 0, 1854, 1853, 14, 77, 81, 1852, 1850, 1848, 1847, - 128, 123, 121, 1844, 1843, 1840, 1839, 1837, 1836, 1835, - 1834, 1833, 1831, 1830, 1829, 62, 115, 114, 1828, 1825, - 1811, 1810, 1807, 126, 124, 473, 1806, 125, 1805, 1803, - 1802, 1801, 1800, 1796, 1794, 1792, 1781, 1780, 1778, 1777, - 199, 1776, 1775, 7, 1774, 83, 1772, 1769, 1768, 1767, - 1760, 1759, 1757, 105, 1756, 44, 226, 48, 75, 1753, - 69, 765, 1746, 96, 111, 1745, 161, 1744, 39, 89, - 68, 1743, 40, 1742, 1738, 86, 1736, 1735, 1734, 73, - 1733, 1731, 2601, 1729, 67, 76, 21, 37, 1728, 1727, - 1726, 1725, 32, 1285, 1724, 1722, 24, 1721, 1720, 127, - 1718, 82, 31, 16, 19, 18, 1717, 79, 1716, 8, - 61, 23, 1713, 80, 1712, 1704, 1701, 1698, 33, 1696, - 74, 100, 116, 1695, 6, 10, 1690, 1689, 1688, 1686, - 1684, 1671, 4, 1670, 1668, 1666, 1665, 26, 1663, 11, - 25, 70, 46, 29, 9, 1662, 119, 1660, 27, 104, - 66, 102, 1659, 1658, 1657, 962, 1656, 59, 1655, 131, - 1654, 1653, 41, 1652, 462, 753, 1648, 1647, 1646, 49, - 1116, 2368, 13, 106, 1643, 1642, 1687, 55, 71, 22, - 1641, 1640, 1637, 122, 45, 51, 939, 43, 1636, 1635, - 1634, 1633, 1631, 1627, 1626, 387, 1625, 1624, 1623, 34, - 20, 110, 30, 1621, 1619, 1617, 1614, 1613, 63, 54, - 1612, 99, 98, 72, 117, 1611, 107, 84, 57, 1609, - 56, 1606, 1605, 1604, 1603, 42, 1602, 1601, 1599, 1598, - 94, 85, 64, 36, 35, 87, 1597, 38, 1596, 1592, - 97, 90, 1591, 17, 113, 12, 1590, 2, 0, 1589, - 5, 109, 1400, 112, 1587, 1585, 1, 1584, 3, 1583, - 1581, 78, 1580, 1579, 1578, 1573, 3031, 28, 103, 1572, - 118, + 0, 1748, 1746, 14, 89, 85, 1745, 1744, 1743, 1740, + 128, 125, 118, 1738, 1737, 1736, 1735, 1733, 1730, 1729, + 1728, 1727, 1726, 1724, 1723, 61, 110, 115, 1722, 1720, + 1719, 1718, 1715, 124, 121, 458, 1708, 122, 1706, 1703, + 1700, 1698, 1694, 1693, 1692, 1691, 1690, 1688, 1684, 1681, + 134, 1675, 1673, 7, 1672, 81, 1670, 1668, 1667, 1666, + 1664, 1662, 1661, 109, 1660, 46, 86, 48, 74, 1659, + 71, 793, 1658, 98, 117, 1657, 161, 1656, 45, 90, + 69, 1655, 43, 1654, 1650, 94, 1649, 1648, 1645, 72, + 1644, 1643, 2430, 1642, 68, 76, 21, 37, 1639, 1638, + 1637, 1636, 38, 1286, 1634, 1633, 26, 1629, 1628, 127, + 1627, 80, 31, 16, 19, 18, 1626, 79, 1625, 8, + 54, 32, 1624, 75, 1623, 1622, 1617, 1616, 33, 1613, + 73, 97, 24, 1611, 6, 10, 1608, 1607, 1606, 1605, + 1604, 1603, 4, 1602, 1601, 1600, 1599, 29, 1598, 11, + 23, 70, 111, 27, 9, 1596, 136, 1593, 25, 106, + 66, 104, 1592, 1591, 1589, 939, 1588, 49, 1587, 132, + 1586, 1585, 41, 1583, 442, 815, 1582, 1580, 1579, 59, + 1117, 2371, 13, 107, 1574, 1572, 1689, 57, 77, 22, + 1571, 1570, 1569, 119, 64, 51, 891, 44, 1567, 1566, + 1565, 1564, 1563, 1561, 1559, 246, 1556, 1555, 1554, 34, + 20, 100, 30, 1552, 1551, 1548, 1547, 1543, 63, 36, + 1541, 103, 102, 62, 116, 1540, 113, 84, 55, 1539, + 56, 1536, 1532, 1528, 1527, 42, 1526, 1525, 1524, 1523, + 99, 82, 67, 40, 35, 96, 1521, 39, 1520, 1519, + 83, 87, 1517, 17, 114, 12, 1515, 3, 0, 1512, + 5, 126, 1355, 112, 1507, 1506, 1, 1505, 2, 1504, + 1503, 78, 1498, 1495, 1488, 1483, 2988, 28, 105, 1479, + 120, } var yyR1 = [...]int{ @@ -4107,28 +4102,28 @@ var yyR1 = [...]int{ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, 107, 107, 107, 107, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, - 105, 106, 106, 106, 106, 106, 106, 106, 106, 106, - 106, 106, 106, 106, 106, 106, 106, 280, 280, 109, - 108, 108, 108, 108, 108, 108, 108, 61, 61, 61, - 61, 61, 195, 195, 195, 197, 197, 197, 197, 197, - 197, 197, 197, 197, 197, 197, 197, 197, 124, 124, - 60, 60, 122, 122, 123, 125, 125, 119, 119, 119, - 102, 102, 102, 102, 102, 102, 102, 102, 104, 104, - 104, 126, 126, 127, 127, 128, 128, 129, 129, 130, - 131, 131, 131, 132, 132, 132, 132, 248, 248, 248, - 248, 248, 243, 243, 243, 243, 244, 244, 244, 71, - 71, 71, 71, 73, 73, 72, 72, 53, 53, 54, - 54, 54, 74, 74, 75, 75, 75, 75, 147, 147, - 147, 133, 133, 133, 133, 138, 138, 138, 134, 134, - 136, 136, 136, 137, 137, 137, 135, 141, 141, 143, - 143, 142, 142, 140, 140, 145, 145, 144, 144, 139, - 139, 101, 101, 101, 101, 101, 148, 148, 148, 148, - 153, 153, 113, 113, 115, 115, 114, 116, 154, 154, - 158, 155, 155, 159, 159, 159, 159, 159, 156, 156, - 157, 157, 185, 185, 185, 163, 163, 174, 174, 175, - 175, 165, 165, 178, 178, 178, 146, 146, 146, 146, - 249, 249, 245, 181, 181, 182, 182, 186, 186, 187, - 187, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 105, 105, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 280, 280, + 109, 108, 108, 108, 108, 108, 108, 108, 61, 61, + 61, 61, 61, 195, 195, 195, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 124, + 124, 60, 60, 122, 122, 123, 125, 125, 119, 119, + 119, 102, 102, 102, 102, 102, 102, 102, 102, 104, + 104, 104, 126, 126, 127, 127, 128, 128, 129, 129, + 130, 131, 131, 131, 132, 132, 132, 132, 248, 248, + 248, 248, 248, 243, 243, 243, 243, 244, 244, 244, + 71, 71, 71, 71, 73, 73, 72, 72, 53, 53, + 54, 54, 54, 74, 74, 75, 75, 75, 75, 147, + 147, 147, 133, 133, 133, 133, 138, 138, 138, 134, + 134, 136, 136, 136, 137, 137, 137, 135, 141, 141, + 143, 143, 142, 142, 140, 140, 145, 145, 144, 144, + 139, 139, 101, 101, 101, 101, 101, 148, 148, 148, + 148, 153, 153, 113, 113, 115, 115, 114, 116, 154, + 154, 158, 155, 155, 159, 159, 159, 159, 159, 156, + 156, 157, 157, 185, 185, 185, 163, 163, 174, 174, + 175, 175, 165, 165, 178, 178, 178, 146, 146, 146, + 146, 249, 249, 245, 181, 181, 182, 182, 186, 186, + 187, 187, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, @@ -4141,7 +4136,7 @@ var yyR1 = [...]int{ 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, + 179, 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, @@ -4166,7 +4161,7 @@ var yyR1 = [...]int{ 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, - 180, 180, 276, 277, 193, 194, 194, 194, + 180, 180, 180, 276, 277, 193, 194, 194, 194, } var yyR2 = [...]int{ @@ -4242,26 +4237,26 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 4, 5, 5, 6, 4, 4, 6, 6, 6, 8, 8, 8, 8, 9, 8, 5, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 8, 8, 0, 2, 3, - 4, 4, 4, 4, 4, 4, 4, 0, 3, 4, - 7, 3, 1, 1, 1, 2, 3, 3, 1, 2, - 2, 1, 2, 1, 2, 2, 1, 2, 0, 1, - 0, 2, 1, 2, 4, 0, 2, 1, 3, 5, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 2, 0, 3, 0, 2, 0, 3, 1, 3, 2, - 0, 1, 1, 0, 2, 4, 4, 0, 2, 2, - 1, 1, 3, 3, 3, 3, 3, 3, 3, 0, - 3, 3, 3, 0, 3, 1, 1, 0, 4, 0, - 1, 1, 0, 3, 1, 3, 2, 1, 0, 2, - 4, 0, 9, 3, 5, 0, 3, 3, 0, 1, - 0, 2, 2, 0, 2, 2, 2, 0, 3, 0, - 3, 0, 3, 0, 4, 0, 3, 0, 4, 0, - 1, 2, 1, 5, 4, 4, 1, 3, 3, 5, - 0, 5, 1, 3, 1, 2, 3, 1, 1, 3, - 3, 1, 3, 3, 3, 3, 3, 2, 1, 2, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, - 3, 0, 1, 0, 1, 1, 0, 1, 1, 1, - 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 8, 8, 0, 2, + 3, 4, 4, 4, 4, 4, 4, 4, 0, 3, + 4, 7, 3, 1, 1, 1, 2, 3, 3, 1, + 2, 2, 1, 2, 1, 2, 2, 1, 2, 0, + 1, 0, 2, 1, 2, 4, 0, 2, 1, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 0, 3, 0, 2, 0, 3, 1, 3, + 2, 0, 1, 1, 0, 2, 4, 4, 0, 2, + 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, + 0, 3, 3, 3, 0, 3, 1, 1, 0, 4, + 0, 1, 1, 0, 3, 1, 3, 2, 1, 0, + 2, 4, 0, 9, 3, 5, 0, 3, 3, 0, + 1, 0, 2, 2, 0, 2, 2, 2, 0, 3, + 0, 3, 0, 3, 0, 4, 0, 3, 0, 4, + 0, 1, 2, 1, 5, 4, 4, 1, 3, 3, + 5, 0, 5, 1, 3, 1, 2, 3, 1, 1, + 3, 3, 1, 3, 3, 3, 3, 3, 2, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 0, 2, + 0, 3, 0, 1, 0, 1, 1, 0, 1, 1, + 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -4300,7 +4295,7 @@ var yyR2 = [...]int{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, } var yyChk = [...]int{ @@ -4357,230 +4352,230 @@ var yyChk = [...]int{ 147, 132, 133, 140, 110, 148, -107, -105, -106, -108, 87, 86, 95, 88, 89, 90, 91, 97, 98, 99, -181, -186, -114, -276, 64, 65, 323, 324, 325, 326, - 331, 327, 112, 53, 312, 321, 320, 319, 316, 317, - 314, 315, 329, 330, 167, 313, 161, 138, 322, -258, - -180, 40, 282, 282, -5, -4, -276, 6, 21, 22, - -132, 18, 17, -277, 82, -59, -69, 59, 60, -70, - 22, 36, 63, 61, -51, -68, 134, -76, -186, -68, - -165, 166, -165, -165, -155, -196, 226, -159, 302, 301, - -182, -157, -181, -179, -156, 299, 157, 341, 108, 23, - 25, 111, 143, 17, 112, 159, 174, 142, 170, 323, - 152, 68, 342, 314, 315, 312, 318, 325, 326, 313, - 280, 30, 11, 344, 26, 184, 22, 36, 136, 154, - 115, 116, 187, 24, 185, 99, 347, 20, 71, 179, - 12, 172, 14, 348, 349, 15, 167, 166, 127, 163, - 66, 9, 148, 27, 124, 62, 350, 29, 351, 352, - 353, 354, 64, 125, 18, 316, 317, 32, 427, 355, - 331, 196, 138, 69, 55, 109, 356, 357, 97, 358, - 100, 72, 106, 16, 67, 38, 359, 197, 360, 169, - 361, 305, 362, 126, 155, 322, 65, 363, 161, 281, - 6, 328, 31, 183, 171, 63, 364, 162, 114, 329, - 330, 165, 98, 5, 168, 33, 10, 70, 73, 319, - 320, 321, 53, 335, 113, 13, 365, 306, 107, 300, - 252, -232, 125, -219, -223, -181, 178, -251, 174, -92, - -241, -240, -181, -71, -175, 167, 163, -175, 322, -33, - -34, -156, 142, 195, 81, 81, -223, -222, -221, -263, - 197, 178, -250, -239, 170, 179, -229, 171, 172, -224, - 163, 29, -263, -224, 169, 179, 197, 197, 105, 197, - 105, 197, 197, 197, 197, 197, 197, 197, 197, 197, - 194, -230, 117, -230, 339, 339, -235, -263, -263, -263, - 165, 34, 34, -178, -224, 165, 23, -230, -230, -156, - 142, -230, -230, -230, -230, 205, 205, -230, -230, -230, + 331, 327, 112, 53, 318, 312, 321, 320, 319, 316, + 317, 314, 315, 329, 330, 167, 313, 161, 138, 322, + -258, -180, 40, 282, 282, -5, -4, -276, 6, 21, + 22, -132, 18, 17, -277, 82, -59, -69, 59, 60, + -70, 22, 36, 63, 61, -51, -68, 134, -76, -186, + -68, -165, 166, -165, -165, -155, -196, 226, -159, 302, + 301, -182, -157, -181, -179, -156, 299, 157, 341, 108, + 23, 25, 111, 143, 17, 112, 159, 174, 142, 170, + 323, 152, 68, 342, 314, 315, 312, 318, 325, 326, + 313, 280, 30, 11, 344, 26, 184, 22, 36, 136, + 154, 115, 116, 187, 24, 185, 99, 347, 20, 71, + 179, 12, 172, 14, 348, 349, 15, 167, 166, 127, + 163, 66, 9, 148, 27, 124, 62, 350, 29, 351, + 352, 353, 354, 64, 125, 18, 316, 317, 32, 427, + 355, 331, 196, 138, 69, 55, 109, 356, 357, 97, + 358, 100, 72, 106, 16, 67, 38, 359, 197, 360, + 169, 361, 305, 362, 126, 155, 322, 65, 363, 161, + 281, 6, 328, 31, 183, 171, 63, 364, 162, 114, + 329, 330, 165, 98, 5, 168, 33, 10, 70, 73, + 319, 320, 321, 53, 335, 113, 13, 365, 306, 107, + 300, 252, -232, 125, -219, -223, -181, 178, -251, 174, + -92, -241, -240, -181, -71, -175, 167, 163, -175, 322, + -33, -34, -156, 142, 195, 81, 81, -223, -222, -221, + -263, 197, 178, -250, -239, 170, 179, -229, 171, 172, + -224, 163, 29, -263, -224, 169, 179, 197, 197, 105, + 197, 105, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 194, -230, 117, -230, 339, 339, -235, -263, -263, + -263, 165, 34, 34, -178, -224, 165, 23, -230, -230, + -156, 142, -230, -230, -230, -230, 205, 205, -230, -230, -230, -230, -230, -230, -230, -230, -230, -230, -230, -230, - -230, -230, -92, -74, 212, 152, 154, 157, 72, 117, - -35, 207, -22, -92, -174, 167, -258, -174, -174, -92, - 149, -92, -172, 125, 13, -172, -172, -172, -172, -172, - 208, 296, 208, 296, 208, 209, 208, 209, 208, -169, - -168, 287, 288, 282, 286, -258, 313, 298, -258, 201, - 162, 202, 164, -225, 163, 34, 175, 209, 282, 204, - -172, -194, -276, -182, -194, -194, 31, 165, -181, -52, - -181, 87, -7, -3, -11, -10, -12, 117, 81, 108, - 106, 107, 124, -76, -100, 127, 109, 125, 126, 111, - 129, 128, 139, 132, 133, 134, 135, 136, 137, 138, - 130, 131, 142, 117, 118, 119, 120, 121, 122, 123, - -164, -276, -117, -276, 150, 151, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, -276, 149, -2, -112, - -4, -276, -276, -276, -276, -276, -276, -276, -276, -124, - -76, -276, -280, -109, -276, -280, -109, -280, -109, -280, - -276, -280, -109, -280, -109, -280, -280, -109, -276, -276, - -276, -276, -276, -276, -276, -193, -270, -271, -95, -92, - -128, -3, -50, -147, 20, 32, -76, -129, -130, -76, - -128, 55, -66, -68, -70, 59, 60, 93, 12, -184, - -183, 23, -181, 87, 149, 12, -93, 27, -92, -78, - -79, -80, -81, -95, -118, -276, 12, -85, -86, -92, - -94, -186, 81, 226, -159, -196, -161, -160, 303, 305, - 117, -185, -181, 87, 30, 82, 81, -92, -198, -201, - -203, -202, -204, -199, -200, 249, 250, 143, 253, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 31, - 186, 245, 246, 247, 248, 265, 266, 267, 268, 269, - 270, 271, 272, 232, 251, 333, 233, 234, 235, 236, - 237, 238, 240, 241, 242, 243, 244, -261, -258, 80, - 82, 81, -205, 80, -74, -92, 109, -258, -258, -230, - -230, 194, -27, -26, -254, 16, -25, -26, 157, 101, - 102, 154, 80, -219, 80, -228, -261, -258, 80, 29, - 169, 168, -227, -224, -227, -228, -258, -119, -181, -186, - -258, 29, 29, -152, -181, -152, -152, 21, -152, 21, - -152, 21, 88, -181, -152, 21, -152, 21, -152, 21, - -152, 21, -152, 21, 30, 74, 75, 30, 77, 78, - 79, -119, -119, -219, -156, -92, -258, 88, 88, -230, - -230, 88, 87, 87, 87, -230, -230, 88, 87, -258, - 87, -264, 180, 221, 223, 88, 88, 88, 88, 30, - 87, -265, 30, 440, 439, 441, 442, 443, 88, 30, - 88, 30, 88, -181, 80, -73, 214, 117, 203, 203, - 162, 162, 216, -92, 215, 217, 218, 40, 81, 165, - -85, 24, 72, -87, -92, -258, -187, -186, -179, 87, - -76, -172, -92, -172, -92, -172, -172, -172, -172, -167, - 12, 127, -226, 12, 127, -167, -194, -194, -92, -194, - -194, -92, -194, -194, -226, -173, 125, 72, -192, 229, - 263, 423, 424, 425, -76, -76, -76, -76, -110, 97, - 109, 98, 99, -103, -111, -114, -117, 92, 127, 125, - 126, 111, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -103, -103, -103, -103, -195, -258, 87, - 143, -258, -102, -102, -181, -67, 22, 36, -66, -182, - -187, -179, -63, -277, -277, -128, -66, -66, -76, -76, - -119, 87, -66, -119, 87, -66, -66, -62, 22, 36, - -122, -123, 113, -119, -277, -103, -181, -181, -66, -67, - -67, -66, -66, 81, -272, 305, 306, 427, -189, 197, - -188, 23, -186, 87, -132, -277, -133, 27, 10, 127, - 81, 19, 81, -131, 25, 26, -132, -104, -181, 88, - 91, -77, 81, 12, -70, -92, -183, 134, -187, -92, - -151, 197, -92, 31, 81, -88, -90, -89, -91, 62, - 66, 68, 63, 64, 65, 69, -190, 23, -78, -3, - -276, -92, -85, -278, 81, 12, 73, -278, 81, 149, - -159, -161, 81, 304, 306, 307, 72, 100, -76, -210, - 142, -237, -236, -235, -219, -221, -222, -223, 82, -176, - 97, 109, -214, 277, -205, -205, -205, -205, -205, -209, - -156, -209, -209, -209, 80, 80, -205, -205, -205, -205, - -211, 80, -211, -211, -212, 80, -212, -251, -76, -247, - -246, -242, -245, 173, 94, 335, 73, -240, -131, 88, - -73, 24, -249, -245, -258, 87, -258, 87, 81, 17, - -220, -219, -120, 221, -253, 197, -250, -241, 80, 29, - -227, -228, -228, 149, -258, 81, 27, 105, 105, 105, - 105, 335, 154, 31, -219, -120, -195, 165, -195, -195, - 87, 87, -171, 448, -85, 164, 220, -75, 318, 87, - 83, -92, -92, -92, -92, -92, 157, 154, 205, -92, - -92, -55, 182, 177, -92, 81, -55, -172, -186, -186, - -92, -172, -92, 87, -92, -181, 97, 98, 99, -111, - -103, -103, -103, -65, 187, 108, -277, -277, -66, -66, - -276, 149, -5, -132, -277, -277, 81, 73, 23, 12, - 12, -277, 12, 12, -277, -277, -66, -125, -123, 115, - -76, -277, -277, 81, 81, -277, -277, -277, -277, -277, - -271, 426, 306, -96, 70, 166, 71, -276, -188, -147, - 38, 46, 57, -76, -76, -130, -147, -163, 20, 12, - 53, 53, -97, 13, -68, -78, -70, 149, -97, -101, - 31, 53, -3, -276, -276, -154, -158, -119, -79, -80, - -80, -79, -80, 62, 62, 62, 67, 62, 67, 62, - -89, -186, -277, -277, -3, -151, 73, -78, -92, -78, - -94, -186, 134, -160, -162, 308, 305, 311, -258, 87, - 81, -235, -223, -207, 30, 97, -215, 278, -209, -209, - -210, -258, 143, -210, -210, -210, -218, 87, -218, 88, - 88, 82, -248, -243, -244, 32, 76, -242, -230, 87, - 37, -181, 82, 164, 72, 16, -149, -181, 81, 82, - -121, 222, -119, 82, -181, 82, -149, -228, -182, -181, - -276, 162, 30, 30, -120, -121, -210, -258, 450, 449, - 82, -92, -72, 212, 219, 80, 84, -260, 73, 203, - 274, 203, 206, 165, -194, -92, -167, -167, -65, 108, - -103, -103, -277, -277, -67, -182, -128, -147, -197, 143, - 249, 186, 247, 243, 263, 254, 276, 245, 277, -195, - -197, -103, -103, -103, -103, 332, -128, 116, -76, 114, - -103, -103, 163, 163, 163, -152, 39, 87, 87, 58, - -92, -126, 14, -76, 134, -132, -153, 72, -154, -113, - -115, -114, -276, -148, -277, -181, -152, -97, 81, 117, - -83, -82, 72, 73, -84, 72, -82, 62, 62, -277, - -97, -78, -97, -97, 149, 305, 309, 310, -235, -208, - 72, -103, -210, -210, 82, 81, 82, 81, 82, 81, - -177, 372, 109, -244, -243, -230, -230, 88, -258, -92, - -92, 17, 81, -219, -119, 53, -247, 82, -252, -253, - -92, -102, -121, -150, 80, 82, -257, 335, -259, -258, - -181, -181, -181, -92, -172, -172, -103, -277, -132, -277, - -205, -205, -205, -212, -205, 237, -205, 237, -277, -277, - 20, 20, 20, 20, -276, -60, 328, -76, 81, 81, - -276, -276, -276, -277, 87, -209, -127, 15, 17, 28, - -153, 81, -277, -277, 81, 53, 149, -277, -128, -158, - -76, -76, 80, -76, -128, -97, -213, 274, 10, -209, - 87, -209, 88, 88, 372, 30, 77, 78, 79, 30, - 74, 75, -150, -149, -181, 199, 181, -277, 81, -216, - 335, 338, 23, -149, -256, -255, -182, 80, 73, -147, - -209, -258, -103, -103, -103, -103, -103, -132, 87, -103, - -103, -149, -277, -149, -149, -189, -209, -135, -140, -169, - -76, -112, 29, -115, 53, -3, -181, -113, -181, -132, - -149, -132, -217, 169, 29, 168, -106, -210, -210, 82, - 82, 23, 200, -92, -253, 339, 339, -3, 82, 81, - 117, -149, -92, -277, -277, -277, -277, -61, 127, 335, - -277, -277, -277, -277, -277, -277, -96, -138, 422, -141, - 42, -142, 43, 10, -113, 149, 82, -206, 94, 29, - 29, -3, -276, 80, -53, 335, -255, -234, -182, 87, - 88, 82, -277, 333, 69, 336, -135, 47, 255, -143, - 51, -144, -139, 52, 17, -154, -181, 87, -53, -103, - 196, -149, -54, 211, 426, -260, 58, 334, 337, -136, - 49, -134, 48, -134, -142, 17, -145, 44, 45, 87, - -277, -277, 82, 174, -257, 58, -137, 50, 72, 100, - 87, 17, 17, -267, -268, 72, 213, 335, 72, 100, - 87, 87, -268, 72, 11, 10, 336, -266, 182, 177, - 180, 31, -266, 337, 176, 30, 97, + -230, -230, -230, -92, -74, 212, 152, 154, 157, 72, + 117, -35, 207, -22, -92, -174, 167, -258, -174, -174, + -92, 149, -92, -172, 125, 13, -172, -172, -172, -172, + -172, 208, 296, 208, 296, 208, 209, 208, 209, 208, + -169, -168, 287, 288, 282, 286, -258, 313, 298, -258, + 201, 162, 202, 164, -225, 163, 34, 175, 209, 282, + 204, -172, -194, -276, -182, -194, -194, 31, 165, -181, + -52, -181, 87, -7, -3, -11, -10, -12, 117, 81, + 108, 106, 107, 124, -76, -100, 127, 109, 125, 126, + 111, 129, 128, 139, 132, 133, 134, 135, 136, 137, + 138, 130, 131, 142, 117, 118, 119, 120, 121, 122, + 123, -164, -276, -117, -276, 150, 151, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -276, 149, -2, + -112, -4, -276, -276, -276, -276, -276, -276, -276, -276, + -124, -76, -276, -280, -276, -280, -109, -276, -280, -109, + -280, -109, -280, -280, -109, -280, -109, -280, -280, -109, + -276, -276, -276, -276, -276, -276, -276, -193, -270, -271, + -95, -92, -128, -3, -50, -147, 20, 32, -76, -129, + -130, -76, -128, 55, -66, -68, -70, 59, 60, 93, + 12, -184, -183, 23, -181, 87, 149, 12, -93, 27, + -92, -78, -79, -80, -81, -95, -118, -276, 12, -85, + -86, -92, -94, -186, 81, 226, -159, -196, -161, -160, + 303, 305, 117, -185, -181, 87, 30, 82, 81, -92, + -198, -201, -203, -202, -204, -199, -200, 249, 250, 143, + 253, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 31, 186, 245, 246, 247, 248, 265, 266, 267, + 268, 269, 270, 271, 272, 232, 251, 333, 233, 234, + 235, 236, 237, 238, 240, 241, 242, 243, 244, -261, + -258, 80, 82, 81, -205, 80, -74, -92, 109, -258, + -258, -230, -230, 194, -27, -26, -254, 16, -25, -26, + 157, 101, 102, 154, 80, -219, 80, -228, -261, -258, + 80, 29, 169, 168, -227, -224, -227, -228, -258, -119, + -181, -186, -258, 29, 29, -152, -181, -152, -152, 21, + -152, 21, -152, 21, 88, -181, -152, 21, -152, 21, + -152, 21, -152, 21, -152, 21, 30, 74, 75, 30, + 77, 78, 79, -119, -119, -219, -156, -92, -258, 88, + 88, -230, -230, 88, 87, 87, 87, -230, -230, 88, + 87, -258, 87, -264, 180, 221, 223, 88, 88, 88, + 88, 30, 87, -265, 30, 440, 439, 441, 442, 443, + 88, 30, 88, 30, 88, -181, 80, -73, 214, 117, + 203, 203, 162, 162, 216, -92, 215, 217, 218, 40, + 81, 165, -85, 24, 72, -87, -92, -258, -187, -186, + -179, 87, -76, -172, -92, -172, -92, -172, -172, -172, + -172, -167, 12, 127, -226, 12, 127, -167, -194, -194, + -92, -194, -194, -92, -194, -194, -226, -173, 125, 72, + -192, 229, 263, 423, 424, 425, -76, -76, -76, -76, + -110, 97, 109, 98, 99, -103, -111, -114, -117, 92, + 127, 125, 126, 111, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -195, + -258, 87, 143, -258, -102, -102, -181, -67, 22, 36, + -66, -182, -187, -179, -63, -277, -277, -128, -66, -66, + -76, -76, -119, 87, -66, -119, 87, -66, -66, -62, + 22, 36, -122, -123, 113, -119, -277, -103, -181, -181, + -66, -67, -67, -66, -66, 81, -272, 305, 306, 427, + -189, 197, -188, 23, -186, 87, -132, -277, -133, 27, + 10, 127, 81, 19, 81, -131, 25, 26, -132, -104, + -181, 88, 91, -77, 81, 12, -70, -92, -183, 134, + -187, -92, -151, 197, -92, 31, 81, -88, -90, -89, + -91, 62, 66, 68, 63, 64, 65, 69, -190, 23, + -78, -3, -276, -92, -85, -278, 81, 12, 73, -278, + 81, 149, -159, -161, 81, 304, 306, 307, 72, 100, + -76, -210, 142, -237, -236, -235, -219, -221, -222, -223, + 82, -176, 97, 109, -214, 277, -205, -205, -205, -205, + -205, -209, -156, -209, -209, -209, 80, 80, -205, -205, + -205, -205, -211, 80, -211, -211, -212, 80, -212, -251, + -76, -247, -246, -242, -245, 173, 94, 335, 73, -240, + -131, 88, -73, 24, -249, -245, -258, 87, -258, 87, + 81, 17, -220, -219, -120, 221, -253, 197, -250, -241, + 80, 29, -227, -228, -228, 149, -258, 81, 27, 105, + 105, 105, 105, 335, 154, 31, -219, -120, -195, 165, + -195, -195, 87, 87, -171, 448, -85, 164, 220, -75, + 318, 87, 83, -92, -92, -92, -92, -92, 157, 154, + 205, -92, -92, -55, 182, 177, -92, 81, -55, -172, + -186, -186, -92, -172, -92, 87, -92, -181, 97, 98, + 99, -111, -103, -103, -103, -65, 187, 108, -277, -277, + -66, -66, -276, 149, -5, -132, -277, -277, 81, 73, + 23, 12, 12, -277, 12, 12, -277, -277, -66, -125, + -123, 115, -76, -277, -277, 81, 81, -277, -277, -277, + -277, -277, -271, 426, 306, -96, 70, 166, 71, -276, + -188, -147, 38, 46, 57, -76, -76, -130, -147, -163, + 20, 12, 53, 53, -97, 13, -68, -78, -70, 149, + -97, -101, 31, 53, -3, -276, -276, -154, -158, -119, + -79, -80, -80, -79, -80, 62, 62, 62, 67, 62, + 67, 62, -89, -186, -277, -277, -3, -151, 73, -78, + -92, -78, -94, -186, 134, -160, -162, 308, 305, 311, + -258, 87, 81, -235, -223, -207, 30, 97, -215, 278, + -209, -209, -210, -258, 143, -210, -210, -210, -218, 87, + -218, 88, 88, 82, -248, -243, -244, 32, 76, -242, + -230, 87, 37, -181, 82, 164, 72, 16, -149, -181, + 81, 82, -121, 222, -119, 82, -181, 82, -149, -228, + -182, -181, -276, 162, 30, 30, -120, -121, -210, -258, + 450, 449, 82, -92, -72, 212, 219, 80, 84, -260, + 73, 203, 274, 203, 206, 165, -194, -92, -167, -167, + -65, 108, -103, -103, -277, -277, -67, -182, -128, -147, + -197, 143, 249, 186, 247, 243, 263, 254, 276, 245, + 277, -195, -197, -103, -103, -103, -103, 332, -128, 116, + -76, 114, -103, -103, 163, 163, 163, -152, 39, 87, + 87, 58, -92, -126, 14, -76, 134, -132, -153, 72, + -154, -113, -115, -114, -276, -148, -277, -181, -152, -97, + 81, 117, -83, -82, 72, 73, -84, 72, -82, 62, + 62, -277, -97, -78, -97, -97, 149, 305, 309, 310, + -235, -208, 72, -103, -210, -210, 82, 81, 82, 81, + 82, 81, -177, 372, 109, -244, -243, -230, -230, 88, + -258, -92, -92, 17, 81, -219, -119, 53, -247, 82, + -252, -253, -92, -102, -121, -150, 80, 82, -257, 335, + -259, -258, -181, -181, -181, -92, -172, -172, -103, -277, + -132, -277, -205, -205, -205, -212, -205, 237, -205, 237, + -277, -277, 20, 20, 20, 20, -276, -60, 328, -76, + 81, 81, -276, -276, -276, -277, 87, -209, -127, 15, + 17, 28, -153, 81, -277, -277, 81, 53, 149, -277, + -128, -158, -76, -76, 80, -76, -128, -97, -213, 274, + 10, -209, 87, -209, 88, 88, 372, 30, 77, 78, + 79, 30, 74, 75, -150, -149, -181, 199, 181, -277, + 81, -216, 335, 338, 23, -149, -256, -255, -182, 80, + 73, -147, -209, -258, -103, -103, -103, -103, -103, -132, + 87, -103, -103, -149, -277, -149, -149, -189, -209, -135, + -140, -169, -76, -112, 29, -115, 53, -3, -181, -113, + -181, -132, -149, -132, -217, 169, 29, 168, -106, -210, + -210, 82, 82, 23, 200, -92, -253, 339, 339, -3, + 82, 81, 117, -149, -92, -277, -277, -277, -277, -61, + 127, 335, -277, -277, -277, -277, -277, -277, -96, -138, + 422, -141, 42, -142, 43, 10, -113, 149, 82, -206, + 94, 29, 29, -3, -276, 80, -53, 335, -255, -234, + -182, 87, 88, 82, -277, 333, 69, 336, -135, 47, + 255, -143, 51, -144, -139, 52, 17, -154, -181, 87, + -53, -103, 196, -149, -54, 211, 426, -260, 58, 334, + 337, -136, 49, -134, 48, -134, -142, 17, -145, 44, + 45, 87, -277, -277, 82, 174, -257, 58, -137, 50, + 72, 100, 87, 17, 17, -267, -268, 72, 213, 335, + 72, 100, 87, 87, -268, 72, 11, 10, 336, -266, + 182, 177, 180, 31, -266, 337, 176, 30, 97, } var yyDef = [...]int{ 32, -2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 785, 0, 523, 523, 523, 523, 523, 523, 523, - 0, 0, -2, -2, -2, 809, 36, 0, 0, 0, + 31, 786, 0, 523, 523, 523, 523, 523, 523, 523, + 0, 0, -2, -2, -2, 810, 36, 0, 0, 0, 0, -2, 481, 482, 0, 484, -2, 0, 0, 493, - 1304, 1304, 1304, 0, 0, 0, 0, 1302, 53, 54, - 499, 500, 501, 1, 3, 0, 527, 793, 0, 0, - -2, 525, 0, 0, 901, 901, 901, 0, 84, 85, - 0, 0, 0, 809, 899, 0, 899, 0, 907, 908, - 909, 104, 105, 88, -2, 109, 110, 0, 114, 367, + 1305, 1305, 1305, 0, 0, 0, 0, 1303, 53, 54, + 499, 500, 501, 1, 3, 0, 527, 794, 0, 0, + -2, 525, 0, 0, 902, 902, 902, 0, 84, 85, + 0, 0, 0, 810, 900, 0, 900, 0, 908, 909, + 910, 104, 105, 88, -2, 109, 110, 0, 114, 367, 328, 370, 326, 356, -2, 319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 331, 223, 223, 0, 0, -2, 319, 319, 319, 0, 0, 0, - 353, 903, 273, 223, 223, 0, 223, 223, 223, 223, + 353, 904, 273, 223, 223, 0, 223, 223, 223, 223, 0, 0, 223, 223, 223, 223, 223, 223, 223, 223, - 223, 223, 223, 223, 223, 223, 223, 0, 103, 822, - 0, 0, 113, 37, 33, 34, 35, 0, 897, 0, - 897, 897, 0, 419, 607, 917, 918, 1054, 1055, 1056, - 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, - 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, - 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, - 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, - 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, - 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, - 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, - 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, - 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, - 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, - 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, - 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, - 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, - 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, - 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, - 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, - 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, - 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, - 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, - 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, - 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, - 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, - 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, - 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, - 1297, 1298, 1299, 1300, 1301, 0, 472, 472, 472, 472, + 223, 223, 223, 223, 223, 223, 223, 0, 103, 823, + 0, 0, 113, 37, 33, 34, 35, 0, 898, 0, + 898, 898, 0, 419, 607, 918, 919, 1055, 1056, 1057, + 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, + 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, + 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, + 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, + 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, + 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, + 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, + 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, + 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, + 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, + 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, + 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, + 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, + 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, + 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, + 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, + 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, + 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, + 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, + 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, + 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, + 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, + 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, + 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, + 1298, 1299, 1300, 1301, 1302, 0, 472, 472, 472, 472, 472, 472, 0, 428, 0, 0, 0, 0, 0, 0, - 0, 444, 0, 447, 0, 0, 454, 472, 1305, 1305, - 1305, 888, 0, 478, 479, 466, 464, 461, 462, 480, - 483, 0, 488, 491, 913, 914, 0, 506, 0, 1125, + 0, 444, 0, 447, 0, 0, 454, 472, 1306, 1306, + 1306, 889, 0, 478, 479, 466, 464, 461, 462, 480, + 483, 0, 488, 491, 914, 915, 0, 506, 0, 1126, 498, 511, 512, 522, 38, 658, 617, 0, 623, 625, 0, 660, 661, 662, 663, 664, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 690, 691, 692, 693, - 770, 771, 772, 773, 774, 775, 776, 777, 627, 628, - 767, 0, 877, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 758, 0, 727, 727, 727, 727, 727, 727, - 727, 727, 0, 0, 0, 0, 0, 0, 0, -2, - -2, 1304, 0, 521, 785, 49, 0, 523, 528, 529, - 828, 0, 0, 785, 1303, 0, 0, -2, -2, 539, - 545, 546, 547, 548, 524, 0, 551, 555, 0, 0, - 0, 902, 0, 0, 70, 0, 1273, 881, -2, -2, - 0, 0, 915, 916, 890, -2, 921, 922, 923, 924, + 771, 772, 773, 774, 775, 776, 777, 778, 627, 628, + 768, 0, 878, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 759, 0, 728, 728, 728, 728, 728, 728, + 728, 728, 728, 0, 0, 0, 0, 0, 0, 0, + -2, -2, 1305, 0, 521, 786, 49, 0, 523, 528, + 529, 829, 0, 0, 786, 1304, 0, 0, -2, -2, + 539, 545, 546, 547, 548, 524, 0, 551, 555, 0, + 0, 0, 903, 0, 0, 70, 0, 1274, 882, -2, + -2, 0, 0, 916, 917, 891, -2, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, @@ -4593,148 +4588,148 @@ var yyDef = [...]int{ 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, - 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, -2, - 1072, 0, 0, 123, 124, 0, 36, 249, 0, 119, - 0, 243, 181, 822, 0, 0, 0, 0, 90, 111, - 112, 223, 223, 0, 113, 113, 335, 336, 337, 0, - 0, -2, 247, 0, 320, 0, 0, 237, 237, 241, - 239, 240, 0, 0, 0, 0, 0, 0, 347, 0, - 348, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 403, 0, 224, 0, 365, 366, 274, 0, 0, 0, - 0, 345, 346, 0, 0, 904, 905, 0, 0, 223, - 223, 0, 0, 0, 0, 223, 223, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 100, 813, 0, 0, 0, 0, 0, 0, - -2, 0, 411, 0, 0, 0, 0, 0, 0, 418, - 0, 420, 421, 0, 0, 422, 423, 424, 425, 426, - 472, 0, 472, 0, 472, 472, 472, 472, 469, 0, - 469, 467, 468, 459, 460, 1305, 1305, 0, 1305, 1305, - 0, 1305, 1305, 0, 232, 233, 234, 475, 451, 452, - 455, 456, 1306, 1307, 457, 458, 889, 489, 492, 509, - 507, 508, 510, 502, 503, 504, 505, 0, 0, 0, - 0, 0, 0, 621, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 645, 646, 647, 648, 649, 650, 651, - 624, 0, 638, 0, 0, 0, 680, 681, 682, 683, - 684, 685, 686, 687, 688, 0, 536, 0, 0, 0, - 785, 0, 0, 0, 0, 0, 0, 0, 533, 0, - 759, 0, 711, 719, 0, 712, 720, 713, 721, 714, - 0, 715, 722, 716, 723, 717, 718, 724, 0, 0, - 0, 536, 536, 0, 0, 39, 513, 514, 0, 590, - 793, 0, 538, 831, 0, 0, 794, 786, 787, 790, - 793, 0, 560, 549, 540, 543, 544, 526, 0, 552, - 556, 0, 558, 559, 0, 0, 68, 0, 606, 0, - 562, 564, 565, 566, 588, 0, 0, 0, 0, 64, - 66, 607, 0, 1273, 887, 0, 72, 73, 0, 0, - 0, 204, 892, 893, 894, -2, 230, 0, 192, 188, - 132, 133, 134, 181, 136, 181, 181, 181, 181, 201, - 201, 201, 201, 164, 165, 166, 167, 168, 0, 0, - 151, 181, 181, 181, 181, 171, 172, 173, 174, 175, - 176, 177, 178, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 183, 183, 183, 185, 185, 0, 37, 0, - 215, 0, 790, 0, 813, 99, 0, 910, 102, 0, - 0, 368, 329, 357, 369, 0, 332, 333, -2, 0, - 0, 319, 0, 321, 0, 231, 0, -2, 0, 0, - 0, 237, 241, 238, 241, 229, 242, 349, 767, 0, - 350, 351, 0, 383, 576, 0, 0, 0, 0, 0, - 389, 390, 391, 0, 393, 394, 395, 396, 397, 398, - 399, 400, 401, 402, 358, 359, 360, 361, 362, 363, - 364, 0, 0, 321, 0, 354, 0, 275, 276, 0, - 0, 279, 280, 281, 282, 0, 0, 285, 286, 287, - 288, 289, 313, 314, 315, 290, 291, 292, 293, 294, - 295, 296, 307, 308, 309, 310, 311, 312, 297, 298, - 299, 300, 301, 304, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 810, 811, 812, 0, 0, 0, - 262, 898, 0, 262, 62, 417, 608, 919, 920, 473, - 474, 427, 445, 429, 448, 430, 432, 431, 433, 472, - 0, 0, 0, 235, 236, 472, 436, 437, 438, 439, - 440, 441, 442, 443, 0, 450, 0, 0, 0, 490, - 494, 495, 496, 497, 659, 618, 619, 620, 622, 639, - 0, 641, 643, 629, 630, 654, 655, 656, 0, 0, - 0, 0, 652, 634, 0, 665, 666, 667, 668, 669, - 670, 671, 672, 673, 674, 675, 676, 679, 742, 743, - 744, 0, 677, 678, 689, 0, 0, 0, 537, 768, - 0, -2, 0, 657, 876, 793, 0, 0, 0, 0, - 662, 770, 0, 662, 770, 0, 0, 0, 534, 535, - 765, 762, 0, 0, 728, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 516, 517, 519, 0, 610, 0, - 591, 0, 593, 594, 828, 50, 40, 0, 829, 0, - 0, 0, 0, 789, 791, 792, 828, 0, 778, 0, - 0, 615, 0, 0, 541, 46, 557, 553, 0, 615, - 0, 0, 605, 0, 0, 0, 0, 0, 0, 595, - 0, 0, 598, 0, 0, 0, 0, 589, 0, 0, - 0, -2, 0, 0, 0, 60, 61, 0, 0, 0, - 882, 71, 0, 0, 76, 77, 883, 884, 885, 886, - 0, 106, -2, 270, 125, 127, 128, 129, 120, 195, - 193, 0, 190, 189, 135, 201, 201, 158, 159, 204, - 0, 204, 204, 204, 0, 0, 152, 153, 154, 155, - 146, 0, 147, 148, 149, 0, 150, 248, 0, 797, - 216, 217, 219, 223, 0, 0, 0, 244, 245, 0, - 0, 900, 0, 911, 115, 116, 117, 118, 113, 0, - 0, 121, 323, 0, 0, 0, 246, 0, 0, 225, - 241, 226, 227, 0, 352, 0, 0, 385, 386, 387, - 388, 0, 0, 0, 321, 323, 204, 0, 277, 278, - 283, 284, 302, 0, 0, 0, 0, 823, 824, 0, - 827, 91, 375, 377, 376, 380, 0, 0, 0, 0, - 412, 414, 263, 264, 1305, 0, 416, 434, 470, 471, - 469, 449, 469, 476, 453, 486, 640, 642, 644, 631, - 652, 635, 0, 632, 0, 0, 626, 694, 0, 0, - 536, 0, 785, 828, 698, 699, 0, 0, 0, 0, - 0, 735, 0, 0, 736, 0, 785, 0, 763, 0, - 0, 710, 729, 0, 0, 730, 731, 732, 733, 734, - 515, 518, 520, 570, 0, 0, 0, 0, 592, 42, - 0, 0, 0, 795, 796, 788, 41, 0, 895, 896, - 779, 780, 781, 0, 550, 561, 542, 0, 793, 870, - 0, 0, 862, 0, 0, 615, 878, 0, 563, 584, - 586, 0, 581, 596, 597, 599, 0, 601, 0, 603, - 604, 567, 568, 569, 0, 615, 0, 615, 65, 615, - 67, 0, 609, 74, 75, 0, 0, 81, 205, 206, - 113, 272, 126, 197, 0, 194, 131, 191, 204, 204, - 160, 202, 203, 161, 162, 163, 0, 179, 0, 0, - 0, 265, 86, 801, 800, 223, 223, 218, 0, 221, - 0, 912, 182, 0, 0, 0, 327, 574, 0, 338, - 339, 0, 322, 382, 0, 215, 0, 228, 768, 577, - 0, 0, 340, 0, 323, 343, 344, 355, 305, 306, - 303, 572, 814, 815, 816, 0, 826, 94, 0, 0, - 0, 0, 373, 0, 415, 63, 472, 472, 633, 0, - 653, 636, 695, 696, 0, 769, 793, 44, 0, 181, - 181, 748, 181, 185, 751, 181, 753, 181, 756, 0, - 0, 0, 0, 0, 0, 0, 760, 709, 766, 0, - 0, 0, 0, 0, 0, 0, 0, 201, 833, 830, - 43, 783, 0, 616, 554, 47, 51, 0, 870, 861, - 872, 874, 0, 0, 0, 866, 0, 785, 0, 0, - 578, 585, 0, 0, 579, 0, 580, 600, 602, -2, - 785, 615, 58, 59, 0, 78, 79, 80, 271, 199, - 0, 196, 156, 157, 201, 0, 201, 0, 186, 0, - 254, 266, 0, 798, 799, 0, 0, 220, 222, 572, - 101, 0, 0, 122, 324, 0, 214, 0, 0, 407, - 404, 341, 342, 0, 0, 825, 374, 0, 92, 93, - 0, 0, 379, 413, 435, 446, 637, 697, 828, 700, - 745, 201, 749, 750, 752, 754, 755, 757, 702, 701, - 0, 0, 0, 0, 0, 793, 0, 764, 0, 0, - 0, 0, 0, 590, 201, 853, 48, 0, 0, 0, - 52, 0, 875, 0, 0, 0, 0, 69, 793, 879, - 880, 582, 0, 587, 793, 57, 207, 200, 0, 204, - 180, 204, 0, 0, 267, 802, 803, 804, 805, 806, - 807, 808, 0, 330, 575, 0, 0, 384, 0, 392, - 0, 0, 0, 0, 95, 96, 0, 0, 0, 45, - 746, 747, 0, 0, 0, 0, 737, 0, 761, 0, - 0, 0, 612, 0, 0, 610, 835, 834, 847, 851, - 784, 782, 0, 873, 0, 865, 868, 864, 867, 55, - 0, 56, 212, 0, 209, 211, 198, 169, 170, 184, - 187, 0, 0, 0, 408, 405, 406, 817, 573, 0, - 0, 0, 381, 703, 705, 704, 706, 0, 0, 0, - 708, 725, 726, 611, 613, 614, 571, 853, 0, 846, - 849, -2, 0, 0, 863, 0, 583, 130, 0, 208, - 210, 817, 0, 0, 371, 819, 97, 98, 316, 317, - 318, 91, 707, 0, 0, 0, 840, 838, 838, 851, - 0, 855, 0, 860, 0, 871, 869, 213, 87, 0, - 0, 0, 0, 820, 821, 94, 738, 0, 741, 843, - 0, 836, 839, 837, 848, 0, 854, 0, 0, 852, - 409, 410, 250, 0, 378, 739, 832, 0, 841, 842, - 850, 0, 0, 251, 252, 0, 818, 0, 844, 845, - 856, 858, 253, 0, 0, 0, 0, 255, 257, 258, - 0, 0, 256, 740, 259, 260, 261, + 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, + -2, 1073, 0, 0, 123, 124, 0, 36, 249, 0, + 119, 0, 243, 181, 823, 0, 0, 0, 0, 90, + 111, 112, 223, 223, 0, 113, 113, 335, 336, 337, + 0, 0, -2, 247, 0, 320, 0, 0, 237, 237, + 241, 239, 240, 0, 0, 0, 0, 0, 0, 347, + 0, 348, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 403, 0, 224, 0, 365, 366, 274, 0, 0, + 0, 0, 345, 346, 0, 0, 905, 906, 0, 0, + 223, 223, 0, 0, 0, 0, 223, 223, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 100, 814, 0, 0, 0, 0, 0, + 0, -2, 0, 411, 0, 0, 0, 0, 0, 0, + 418, 0, 420, 421, 0, 0, 422, 423, 424, 425, + 426, 472, 0, 472, 0, 472, 472, 472, 472, 469, + 0, 469, 467, 468, 459, 460, 1306, 1306, 0, 1306, + 1306, 0, 1306, 1306, 0, 232, 233, 234, 475, 451, + 452, 455, 456, 1307, 1308, 457, 458, 890, 489, 492, + 509, 507, 508, 510, 502, 503, 504, 505, 0, 0, + 0, 0, 0, 0, 621, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 645, 646, 647, 648, 649, 650, + 651, 624, 0, 638, 0, 0, 0, 680, 681, 682, + 683, 684, 685, 686, 687, 688, 0, 536, 0, 0, + 0, 786, 0, 0, 0, 0, 0, 0, 0, 533, + 0, 760, 0, 711, 0, 712, 720, 0, 713, 721, + 714, 722, 715, 716, 723, 717, 724, 718, 719, 725, + 0, 0, 0, 536, 536, 0, 0, 39, 513, 514, + 0, 590, 794, 0, 538, 832, 0, 0, 795, 787, + 788, 791, 794, 0, 560, 549, 540, 543, 544, 526, + 0, 552, 556, 0, 558, 559, 0, 0, 68, 0, + 606, 0, 562, 564, 565, 566, 588, 0, 0, 0, + 0, 64, 66, 607, 0, 1274, 888, 0, 72, 73, + 0, 0, 0, 204, 893, 894, 895, -2, 230, 0, + 192, 188, 132, 133, 134, 181, 136, 181, 181, 181, + 181, 201, 201, 201, 201, 164, 165, 166, 167, 168, + 0, 0, 151, 181, 181, 181, 181, 171, 172, 173, + 174, 175, 176, 177, 178, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 183, 183, 183, 185, 185, 0, + 37, 0, 215, 0, 791, 0, 814, 99, 0, 911, + 102, 0, 0, 368, 329, 357, 369, 0, 332, 333, + -2, 0, 0, 319, 0, 321, 0, 231, 0, -2, + 0, 0, 0, 237, 241, 238, 241, 229, 242, 349, + 768, 0, 350, 351, 0, 383, 576, 0, 0, 0, + 0, 0, 389, 390, 391, 0, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 358, 359, 360, 361, + 362, 363, 364, 0, 0, 321, 0, 354, 0, 275, + 276, 0, 0, 279, 280, 281, 282, 0, 0, 285, + 286, 287, 288, 289, 313, 314, 315, 290, 291, 292, + 293, 294, 295, 296, 307, 308, 309, 310, 311, 312, + 297, 298, 299, 300, 301, 304, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 811, 812, 813, 0, + 0, 0, 262, 899, 0, 262, 62, 417, 608, 920, + 921, 473, 474, 427, 445, 429, 448, 430, 432, 431, + 433, 472, 0, 0, 0, 235, 236, 472, 436, 437, + 438, 439, 440, 441, 442, 443, 0, 450, 0, 0, + 0, 490, 494, 495, 496, 497, 659, 618, 619, 620, + 622, 639, 0, 641, 643, 629, 630, 654, 655, 656, + 0, 0, 0, 0, 652, 634, 0, 665, 666, 667, + 668, 669, 670, 671, 672, 673, 674, 675, 676, 679, + 743, 744, 745, 0, 677, 678, 689, 0, 0, 0, + 537, 769, 0, -2, 0, 657, 877, 794, 0, 0, + 0, 0, 662, 771, 0, 662, 771, 0, 0, 0, + 534, 535, 766, 763, 0, 0, 729, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 516, 517, 519, 0, + 610, 0, 591, 0, 593, 594, 829, 50, 40, 0, + 830, 0, 0, 0, 0, 790, 792, 793, 829, 0, + 779, 0, 0, 615, 0, 0, 541, 46, 557, 553, + 0, 615, 0, 0, 605, 0, 0, 0, 0, 0, + 0, 595, 0, 0, 598, 0, 0, 0, 0, 589, + 0, 0, 0, -2, 0, 0, 0, 60, 61, 0, + 0, 0, 883, 71, 0, 0, 76, 77, 884, 885, + 886, 887, 0, 106, -2, 270, 125, 127, 128, 129, + 120, 195, 193, 0, 190, 189, 135, 201, 201, 158, + 159, 204, 0, 204, 204, 204, 0, 0, 152, 153, + 154, 155, 146, 0, 147, 148, 149, 0, 150, 248, + 0, 798, 216, 217, 219, 223, 0, 0, 0, 244, + 245, 0, 0, 901, 0, 912, 115, 116, 117, 118, + 113, 0, 0, 121, 323, 0, 0, 0, 246, 0, + 0, 225, 241, 226, 227, 0, 352, 0, 0, 385, + 386, 387, 388, 0, 0, 0, 321, 323, 204, 0, + 277, 278, 283, 284, 302, 0, 0, 0, 0, 824, + 825, 0, 828, 91, 375, 377, 376, 380, 0, 0, + 0, 0, 412, 414, 263, 264, 1306, 0, 416, 434, + 470, 471, 469, 449, 469, 476, 453, 486, 640, 642, + 644, 631, 652, 635, 0, 632, 0, 0, 626, 694, + 0, 0, 536, 0, 786, 829, 698, 699, 0, 0, + 0, 0, 0, 736, 0, 0, 737, 0, 786, 0, + 764, 0, 0, 710, 730, 0, 0, 731, 732, 733, + 734, 735, 515, 518, 520, 570, 0, 0, 0, 0, + 592, 42, 0, 0, 0, 796, 797, 789, 41, 0, + 896, 897, 780, 781, 782, 0, 550, 561, 542, 0, + 794, 871, 0, 0, 863, 0, 0, 615, 879, 0, + 563, 584, 586, 0, 581, 596, 597, 599, 0, 601, + 0, 603, 604, 567, 568, 569, 0, 615, 0, 615, + 65, 615, 67, 0, 609, 74, 75, 0, 0, 81, + 205, 206, 113, 272, 126, 197, 0, 194, 131, 191, + 204, 204, 160, 202, 203, 161, 162, 163, 0, 179, + 0, 0, 0, 265, 86, 802, 801, 223, 223, 218, + 0, 221, 0, 913, 182, 0, 0, 0, 327, 574, + 0, 338, 339, 0, 322, 382, 0, 215, 0, 228, + 769, 577, 0, 0, 340, 0, 323, 343, 344, 355, + 305, 306, 303, 572, 815, 816, 817, 0, 827, 94, + 0, 0, 0, 0, 373, 0, 415, 63, 472, 472, + 633, 0, 653, 636, 695, 696, 0, 770, 794, 44, + 0, 181, 181, 749, 181, 185, 752, 181, 754, 181, + 757, 0, 0, 0, 0, 0, 0, 0, 761, 709, + 767, 0, 0, 0, 0, 0, 0, 0, 0, 201, + 834, 831, 43, 784, 0, 616, 554, 47, 51, 0, + 871, 862, 873, 875, 0, 0, 0, 867, 0, 786, + 0, 0, 578, 585, 0, 0, 579, 0, 580, 600, + 602, -2, 786, 615, 58, 59, 0, 78, 79, 80, + 271, 199, 0, 196, 156, 157, 201, 0, 201, 0, + 186, 0, 254, 266, 0, 799, 800, 0, 0, 220, + 222, 572, 101, 0, 0, 122, 324, 0, 214, 0, + 0, 407, 404, 341, 342, 0, 0, 826, 374, 0, + 92, 93, 0, 0, 379, 413, 435, 446, 637, 697, + 829, 700, 746, 201, 750, 751, 753, 755, 756, 758, + 702, 701, 0, 0, 0, 0, 0, 794, 0, 765, + 0, 0, 0, 0, 0, 590, 201, 854, 48, 0, + 0, 0, 52, 0, 876, 0, 0, 0, 0, 69, + 794, 880, 881, 582, 0, 587, 794, 57, 207, 200, + 0, 204, 180, 204, 0, 0, 267, 803, 804, 805, + 806, 807, 808, 809, 0, 330, 575, 0, 0, 384, + 0, 392, 0, 0, 0, 0, 95, 96, 0, 0, + 0, 45, 747, 748, 0, 0, 0, 0, 738, 0, + 762, 0, 0, 0, 612, 0, 0, 610, 836, 835, + 848, 852, 785, 783, 0, 874, 0, 866, 869, 865, + 868, 55, 0, 56, 212, 0, 209, 211, 198, 169, + 170, 184, 187, 0, 0, 0, 408, 405, 406, 818, + 573, 0, 0, 0, 381, 703, 705, 704, 706, 0, + 0, 0, 708, 726, 727, 611, 613, 614, 571, 854, + 0, 847, 850, -2, 0, 0, 864, 0, 583, 130, + 0, 208, 210, 818, 0, 0, 371, 820, 97, 98, + 316, 317, 318, 91, 707, 0, 0, 0, 841, 839, + 839, 852, 0, 856, 0, 861, 0, 872, 870, 213, + 87, 0, 0, 0, 0, 821, 822, 94, 739, 0, + 742, 844, 0, 837, 840, 838, 849, 0, 855, 0, + 0, 853, 409, 410, 250, 0, 378, 740, 833, 0, + 842, 843, 851, 0, 0, 251, 252, 0, 819, 0, + 845, 846, 857, 859, 253, 0, 0, 0, 0, 255, + 257, 258, 0, 0, 256, 741, 259, 260, 261, } var yyTok1 = [...]int{ @@ -9279,141 +9274,141 @@ yydefault: } case 711: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3626 +//line sql.y:3620 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} + yyVAL.expr = &FuncExpr{Name: NewColIdent(string(yyDollar[1].bytes))} } case 712: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3630 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_timestamp")} } case 713: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3634 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_timestamp")} } case 714: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3639 +//line sql.y:3638 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_time")} } case 715: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3644 +//line sql.y:3643 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("utc_date")} } case 716: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3649 +//line sql.y:3648 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("localtime")} } case 717: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3655 +//line sql.y:3653 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("localtimestamp")} } case 718: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3660 +//line sql.y:3659 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_date")} } case 719: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3665 +//line sql.y:3664 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} + yyVAL.expr = &FuncExpr{Name: NewColIdent("current_time")} } case 720: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3669 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_timestamp"), Fsp: yyDollar[2].expr} } case 721: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3673 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_timestamp"), Fsp: yyDollar[2].expr} } case 722: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3678 +//line sql.y:3677 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("utc_time"), Fsp: yyDollar[2].expr} } case 723: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3683 +//line sql.y:3682 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtime"), Fsp: yyDollar[2].expr} } case 724: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3688 +//line sql.y:3687 { - yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("localtimestamp"), Fsp: yyDollar[2].expr} } case 725: - yyDollar = yyS[yypt-8 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3692 { - yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} + yyVAL.expr = &CurTimeFuncExpr{Name: NewColIdent("current_time"), Fsp: yyDollar[2].expr} } case 726: yyDollar = yyS[yypt-8 : yypt+1] //line sql.y:3696 { - yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} + yyVAL.expr = &TimestampFuncExpr{Name: string("timestampadd"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } - case 729: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3706 + case 727: + yyDollar = yyS[yypt-8 : yypt+1] +//line sql.y:3700 { - yyVAL.expr = yyDollar[2].expr + yyVAL.expr = &TimestampFuncExpr{Name: string("timestampdiff"), Unit: yyDollar[3].colIdent.String(), Expr1: yyDollar[5].expr, Expr2: yyDollar[7].expr} } case 730: - yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3716 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3710 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = yyDollar[2].expr } case 731: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3720 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("if"), Exprs: yyDollar[3].selectExprs} } case 732: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3724 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("schema"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("database"), Exprs: yyDollar[3].selectExprs} } case 733: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3728 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("schema"), Exprs: yyDollar[3].selectExprs} } case 734: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3732 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("mod"), Exprs: yyDollar[3].selectExprs} } case 735: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3736 { - yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} + yyVAL.expr = &FuncExpr{Name: NewColIdent("replace"), Exprs: yyDollar[3].selectExprs} } case 736: yyDollar = yyS[yypt-4 : yypt+1] @@ -9422,46 +9417,46 @@ yydefault: yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 737: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3746 + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:3744 { - yyVAL.matchExprOption = NoOption + yyVAL.expr = &FuncExpr{Name: NewColIdent("substr"), Exprs: yyDollar[3].selectExprs} } case 738: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:3750 { - yyVAL.matchExprOption = BooleanModeOpt + yyVAL.matchExprOption = NoOption } case 739: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:3754 { - yyVAL.matchExprOption = NaturalLanguageModeOpt + yyVAL.matchExprOption = BooleanModeOpt } case 740: - yyDollar = yyS[yypt-7 : yypt+1] + yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:3758 { - yyVAL.matchExprOption = NaturalLanguageModeWithQueryExpansionOpt + yyVAL.matchExprOption = NaturalLanguageModeOpt } case 741: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-7 : yypt+1] //line sql.y:3762 { - yyVAL.matchExprOption = QueryExpansionOpt + yyVAL.matchExprOption = NaturalLanguageModeWithQueryExpansionOpt } case 742: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3768 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:3766 { - yyVAL.str = string(yyDollar[1].colIdent.String()) + yyVAL.matchExprOption = QueryExpansionOpt } case 743: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3772 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.str = string(yyDollar[1].colIdent.String()) } case 744: yyDollar = yyS[yypt-1 : yypt+1] @@ -9470,63 +9465,63 @@ yydefault: yyVAL.str = string(yyDollar[1].bytes) } case 745: - yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3782 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3780 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} + yyVAL.str = string(yyDollar[1].bytes) } case 746: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3786 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Operator: CharacterSetOp} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 747: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:3790 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: string(yyDollar[3].colIdent.String())} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: yyDollar[3].str, Operator: CharacterSetOp} } case 748: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:3794 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal, Charset: string(yyDollar[3].colIdent.String())} } case 749: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3798 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 750: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3802 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} - yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length - yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 751: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3808 + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3806 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType.Length = yyDollar[2].LengthScaleOption.Length + yyVAL.convertType.Scale = yyDollar[2].LengthScaleOption.Scale } case 752: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3812 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 753: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3816 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 754: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3820 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} @@ -9535,143 +9530,149 @@ yydefault: yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3824 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 756: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:3828 { - yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes), Length: yyDollar[2].literal} } case 757: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3832 { yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} } case 758: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:3836 + { + yyVAL.convertType = &ConvertType{Type: string(yyDollar[1].bytes)} + } + case 759: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3837 +//line sql.y:3841 { yyVAL.expr = nil } - case 759: + case 760: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3841 +//line sql.y:3845 { yyVAL.expr = yyDollar[1].expr } - case 760: + case 761: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3846 +//line sql.y:3850 { yyVAL.str = string("") } - case 761: + case 762: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3850 +//line sql.y:3854 { yyVAL.str = " separator '" + string(yyDollar[2].bytes) + "'" } - case 762: + case 763: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3856 +//line sql.y:3860 { yyVAL.whens = []*When{yyDollar[1].when} } - case 763: + case 764: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3860 +//line sql.y:3864 { yyVAL.whens = append(yyDollar[1].whens, yyDollar[2].when) } - case 764: + case 765: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:3866 +//line sql.y:3870 { yyVAL.when = &When{Cond: yyDollar[2].expr, Val: yyDollar[4].expr} } - case 765: + case 766: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3871 +//line sql.y:3875 { yyVAL.expr = nil } - case 766: + case 767: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3875 +//line sql.y:3879 { yyVAL.expr = yyDollar[2].expr } - case 767: + case 768: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3881 +//line sql.y:3885 { yyVAL.colName = &ColName{Name: yyDollar[1].colIdent} } - case 768: + case 769: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3885 +//line sql.y:3889 { yyVAL.colName = &ColName{Qualifier: TableName{Name: yyDollar[1].tableIdent}, Name: yyDollar[3].colIdent} } - case 769: + case 770: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:3889 +//line sql.y:3893 { yyVAL.colName = &ColName{Qualifier: TableName{Qualifier: yyDollar[1].tableIdent, Name: yyDollar[3].tableIdent}, Name: yyDollar[5].colIdent} } - case 770: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3895 - { - yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) - } case 771: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3899 { - yyVAL.expr = NewHexLiteral(yyDollar[1].bytes) + yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } case 772: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3903 { - yyVAL.expr = NewBitLiteral(yyDollar[1].bytes) + yyVAL.expr = NewHexLiteral(yyDollar[1].bytes) } case 773: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3907 { - yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) + yyVAL.expr = NewBitLiteral(yyDollar[1].bytes) } case 774: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3911 { - yyVAL.expr = NewFloatLiteral(yyDollar[1].bytes) + yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } case 775: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3915 { - yyVAL.expr = NewHexNumLiteral(yyDollar[1].bytes) + yyVAL.expr = NewFloatLiteral(yyDollar[1].bytes) } case 776: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3919 { - yyVAL.expr = NewArgument(yyDollar[1].bytes) + yyVAL.expr = NewHexNumLiteral(yyDollar[1].bytes) } case 777: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3923 { - yyVAL.expr = &NullVal{} + yyVAL.expr = NewArgument(yyDollar[1].bytes) } case 778: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3929 +//line sql.y:3927 + { + yyVAL.expr = &NullVal{} + } + case 779: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:3933 { // TODO(sougou): Deprecate this construct. if yyDollar[1].colIdent.Lowered() != "value" { @@ -9680,80 +9681,74 @@ yydefault: } yyVAL.expr = NewIntLiteral([]byte("1")) } - case 779: + case 780: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3938 +//line sql.y:3942 { yyVAL.expr = NewIntLiteral(yyDollar[1].bytes) } - case 780: + case 781: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3942 +//line sql.y:3946 { yyVAL.expr = NewArgument(yyDollar[1].bytes) } - case 781: + case 782: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3947 +//line sql.y:3951 { yyVAL.exprs = nil } - case 782: + case 783: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3951 +//line sql.y:3955 { yyVAL.exprs = yyDollar[3].exprs } - case 783: + case 784: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3956 +//line sql.y:3960 { yyVAL.expr = nil } - case 784: + case 785: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3960 +//line sql.y:3964 { yyVAL.expr = yyDollar[2].expr } - case 785: + case 786: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3965 +//line sql.y:3969 { yyVAL.orderBy = nil } - case 786: + case 787: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3969 +//line sql.y:3973 { yyVAL.orderBy = yyDollar[3].orderBy } - case 787: + case 788: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:3975 +//line sql.y:3979 { yyVAL.orderBy = OrderBy{yyDollar[1].order} } - case 788: + case 789: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:3979 +//line sql.y:3983 { yyVAL.orderBy = append(yyDollar[1].orderBy, yyDollar[3].order) } - case 789: + case 790: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:3985 +//line sql.y:3989 { yyVAL.order = &Order{Expr: yyDollar[1].expr, Direction: yyDollar[2].orderDirection} } - case 790: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:3990 - { - yyVAL.orderDirection = AscOrder - } case 791: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:3994 { yyVAL.orderDirection = AscOrder @@ -9762,43 +9757,43 @@ yydefault: yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:3998 { - yyVAL.orderDirection = DescOrder + yyVAL.orderDirection = AscOrder } case 793: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4003 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4002 { - yyVAL.limit = nil + yyVAL.orderDirection = DescOrder } case 794: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4007 { - yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} + yyVAL.limit = nil } case 795: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:4011 { - yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} + yyVAL.limit = &Limit{Rowcount: yyDollar[2].expr} } case 796: yyDollar = yyS[yypt-4 : yypt+1] //line sql.y:4015 { - yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} + yyVAL.limit = &Limit{Offset: yyDollar[2].expr, Rowcount: yyDollar[4].expr} } case 797: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4020 + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:4019 { - yyVAL.indexOptions = nil + yyVAL.limit = &Limit{Offset: yyDollar[4].expr, Rowcount: yyDollar[2].expr} } case 798: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4024 { - yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption, yyDollar[2].indexOption} + yyVAL.indexOptions = nil } case 799: yyDollar = yyS[yypt-2 : yypt+1] @@ -9807,10 +9802,10 @@ yydefault: yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption, yyDollar[2].indexOption} } case 800: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-2 : yypt+1] //line sql.y:4032 { - yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption, yyDollar[2].indexOption} } case 801: yyDollar = yyS[yypt-1 : yypt+1] @@ -9819,10 +9814,10 @@ yydefault: yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } case 802: - yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4043 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4040 { - yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} + yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } case 803: yyDollar = yyS[yypt-3 : yypt+1] @@ -9844,7 +9839,7 @@ yydefault: } case 806: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4061 +//line sql.y:4059 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } @@ -9861,16 +9856,16 @@ yydefault: yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } case 809: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4074 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:4073 { - yyVAL.str = "" + yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[3].bytes)} } case 810: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4078 { - yyVAL.str = string(yyDollar[3].bytes) + yyVAL.str = "" } case 811: yyDollar = yyS[yypt-3 : yypt+1] @@ -9885,22 +9880,22 @@ yydefault: yyVAL.str = string(yyDollar[3].bytes) } case 813: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4091 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:4090 { - yyVAL.str = "" + yyVAL.str = string(yyDollar[3].bytes) } case 814: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4095 { - yyVAL.str = yyDollar[3].str + yyVAL.str = "" } case 815: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4101 + yyDollar = yyS[yypt-3 : yypt+1] +//line sql.y:4099 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.str = yyDollar[3].str } case 816: yyDollar = yyS[yypt-1 : yypt+1] @@ -9909,28 +9904,28 @@ yydefault: yyVAL.str = string(yyDollar[1].bytes) } case 817: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4110 + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4109 { - yyVAL.str = "" + yyVAL.str = string(yyDollar[1].bytes) } case 818: - yyDollar = yyS[yypt-4 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4114 { - yyVAL.str = yyDollar[2].str + yyVAL.str = "" } case 819: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4119 + yyDollar = yyS[yypt-4 : yypt+1] +//line sql.y:4118 { - yyVAL.str = "cascaded" + yyVAL.str = yyDollar[2].str } case 820: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4123 { - yyVAL.str = string(yyDollar[1].bytes) + yyVAL.str = "cascaded" } case 821: yyDollar = yyS[yypt-1 : yypt+1] @@ -9939,338 +9934,344 @@ yydefault: yyVAL.str = string(yyDollar[1].bytes) } case 822: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4131 + { + yyVAL.str = string(yyDollar[1].bytes) + } + case 823: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4132 +//line sql.y:4136 { yyVAL.str = "" } - case 823: + case 824: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4136 +//line sql.y:4140 { yyVAL.str = yyDollar[3].str } - case 824: + case 825: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4142 +//line sql.y:4146 { yyVAL.str = string(yyDollar[1].bytes) } - case 825: + case 826: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4146 +//line sql.y:4150 { yyVAL.str = string(yyDollar[1].bytes) } - case 826: + case 827: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4150 +//line sql.y:4154 { yyVAL.str = "'" + string(yyDollar[1].bytes) + "'@" + string(yyDollar[2].bytes) } - case 827: + case 828: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4154 +//line sql.y:4158 { yyVAL.str = string(yyDollar[1].bytes) } - case 828: + case 829: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4159 +//line sql.y:4163 { yyVAL.lock = NoLock } - case 829: + case 830: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4163 +//line sql.y:4167 { yyVAL.lock = ForUpdateLock } - case 830: + case 831: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:4167 +//line sql.y:4171 { yyVAL.lock = ShareModeLock } - case 831: + case 832: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4172 +//line sql.y:4176 { yyVAL.selectInto = nil } - case 832: + case 833: yyDollar = yyS[yypt-9 : yypt+1] -//line sql.y:4176 +//line sql.y:4180 { yyVAL.selectInto = &SelectInto{Type: IntoOutfileS3, FileName: string(yyDollar[4].bytes), Charset: yyDollar[5].str, FormatOption: yyDollar[6].str, ExportOption: yyDollar[7].str, Manifest: yyDollar[8].str, Overwrite: yyDollar[9].str} } - case 833: + case 834: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4180 +//line sql.y:4184 { yyVAL.selectInto = &SelectInto{Type: IntoDumpfile, FileName: string(yyDollar[3].bytes), Charset: "", FormatOption: "", ExportOption: "", Manifest: "", Overwrite: ""} } - case 834: + case 835: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:4184 +//line sql.y:4188 { yyVAL.selectInto = &SelectInto{Type: IntoOutfile, FileName: string(yyDollar[3].bytes), Charset: yyDollar[4].str, FormatOption: "", ExportOption: yyDollar[5].str, Manifest: "", Overwrite: ""} } - case 835: + case 836: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4189 +//line sql.y:4193 { yyVAL.str = "" } - case 836: + case 837: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4193 +//line sql.y:4197 { yyVAL.str = " format csv" + yyDollar[3].str } - case 837: + case 838: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4197 +//line sql.y:4201 { yyVAL.str = " format text" + yyDollar[3].str } - case 838: + case 839: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4202 +//line sql.y:4206 { yyVAL.str = "" } - case 839: + case 840: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4206 +//line sql.y:4210 { yyVAL.str = " header" } - case 840: + case 841: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4211 +//line sql.y:4215 { yyVAL.str = "" } - case 841: + case 842: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4215 +//line sql.y:4219 { yyVAL.str = " manifest on" } - case 842: + case 843: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4219 +//line sql.y:4223 { yyVAL.str = " manifest off" } - case 843: + case 844: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4224 +//line sql.y:4228 { yyVAL.str = "" } - case 844: + case 845: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4228 +//line sql.y:4232 { yyVAL.str = " overwrite on" } - case 845: + case 846: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4232 +//line sql.y:4236 { yyVAL.str = " overwrite off" } - case 846: + case 847: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4238 +//line sql.y:4242 { yyVAL.str = yyDollar[1].str + yyDollar[2].str } - case 847: + case 848: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4243 +//line sql.y:4247 { yyVAL.str = "" } - case 848: + case 849: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4247 +//line sql.y:4251 { yyVAL.str = " lines" + yyDollar[2].str + yyDollar[3].str } - case 849: + case 850: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4252 +//line sql.y:4256 { yyVAL.str = "" } - case 850: + case 851: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4256 +//line sql.y:4260 { yyVAL.str = " starting by '" + string(yyDollar[3].bytes) + "'" } - case 851: + case 852: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4261 +//line sql.y:4265 { yyVAL.str = "" } - case 852: + case 853: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4265 +//line sql.y:4269 { yyVAL.str = " terminated by '" + string(yyDollar[3].bytes) + "'" } - case 853: + case 854: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4270 +//line sql.y:4274 { yyVAL.str = "" } - case 854: + case 855: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:4274 +//line sql.y:4278 { yyVAL.str = " " + yyDollar[1].str + yyDollar[2].str + yyDollar[3].str + yyDollar[4].str } - case 855: + case 856: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4279 +//line sql.y:4283 { yyVAL.str = "" } - case 856: + case 857: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4283 +//line sql.y:4287 { yyVAL.str = " escaped by '" + string(yyDollar[3].bytes) + "'" } - case 857: + case 858: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4288 +//line sql.y:4292 { yyVAL.str = "" } - case 858: + case 859: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:4292 +//line sql.y:4296 { yyVAL.str = yyDollar[1].str + " enclosed by '" + string(yyDollar[4].bytes) + "'" } - case 859: + case 860: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4297 +//line sql.y:4301 { yyVAL.str = "" } - case 860: + case 861: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4301 +//line sql.y:4305 { yyVAL.str = " optionally" } - case 861: + case 862: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4314 +//line sql.y:4318 { yyVAL.ins = &Insert{Rows: yyDollar[2].values} } - case 862: + case 863: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4318 +//line sql.y:4322 { yyVAL.ins = &Insert{Rows: yyDollar[1].selStmt} } - case 863: + case 864: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:4322 +//line sql.y:4326 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[5].values} } - case 864: + case 865: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:4326 +//line sql.y:4330 { yyVAL.ins = &Insert{Rows: yyDollar[4].values} } - case 865: + case 866: yyDollar = yyS[yypt-4 : yypt+1] -//line sql.y:4330 +//line sql.y:4334 { yyVAL.ins = &Insert{Columns: yyDollar[2].columns, Rows: yyDollar[4].selStmt} } - case 866: + case 867: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4336 +//line sql.y:4340 { yyVAL.columns = Columns{yyDollar[1].colIdent} } - case 867: + case 868: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4340 +//line sql.y:4344 { yyVAL.columns = Columns{yyDollar[3].colIdent} } - case 868: + case 869: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4344 +//line sql.y:4348 { yyVAL.columns = append(yyVAL.columns, yyDollar[3].colIdent) } - case 869: + case 870: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:4348 +//line sql.y:4352 { yyVAL.columns = append(yyVAL.columns, yyDollar[5].colIdent) } - case 870: + case 871: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4353 +//line sql.y:4357 { yyVAL.updateExprs = nil } - case 871: + case 872: yyDollar = yyS[yypt-5 : yypt+1] -//line sql.y:4357 +//line sql.y:4361 { yyVAL.updateExprs = yyDollar[5].updateExprs } - case 872: + case 873: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4363 +//line sql.y:4367 { yyVAL.values = Values{yyDollar[1].valTuple} } - case 873: + case 874: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4367 +//line sql.y:4371 { yyVAL.values = append(yyDollar[1].values, yyDollar[3].valTuple) } - case 874: + case 875: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4373 +//line sql.y:4377 { yyVAL.valTuple = yyDollar[1].valTuple } - case 875: + case 876: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4377 +//line sql.y:4381 { yyVAL.valTuple = ValTuple{} } - case 876: + case 877: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4383 +//line sql.y:4387 { yyVAL.valTuple = ValTuple(yyDollar[2].exprs) } - case 877: + case 878: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4389 +//line sql.y:4393 { if len(yyDollar[1].valTuple) == 1 { yyVAL.expr = yyDollar[1].valTuple[0] @@ -10278,252 +10279,246 @@ yydefault: yyVAL.expr = yyDollar[1].valTuple } } - case 878: + case 879: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4399 +//line sql.y:4403 { yyVAL.updateExprs = UpdateExprs{yyDollar[1].updateExpr} } - case 879: + case 880: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4403 +//line sql.y:4407 { yyVAL.updateExprs = append(yyDollar[1].updateExprs, yyDollar[3].updateExpr) } - case 880: + case 881: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4409 +//line sql.y:4413 { yyVAL.updateExpr = &UpdateExpr{Name: yyDollar[1].colName, Expr: yyDollar[3].expr} } - case 881: - yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4415 - { - yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} - } case 882: - yyDollar = yyS[yypt-3 : yypt+1] + yyDollar = yyS[yypt-1 : yypt+1] //line sql.y:4419 { - yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) + yyVAL.setExprs = SetExprs{yyDollar[1].setExpr} } case 883: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4425 +//line sql.y:4423 { - yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("on"))} + yyVAL.setExprs = append(yyDollar[1].setExprs, yyDollar[3].setExpr) } case 884: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:4429 { - yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("off"))} + yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("on"))} } case 885: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:4433 { - yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: yyDollar[3].expr} + yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: NewStrLiteral([]byte("off"))} } case 886: yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:4437 { - yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Scope: ImplicitScope, Expr: yyDollar[2].expr} + yyVAL.setExpr = &SetExpr{Name: yyDollar[1].colIdent, Scope: ImplicitScope, Expr: yyDollar[3].expr} } case 887: - yyDollar = yyS[yypt-2 : yypt+1] + yyDollar = yyS[yypt-3 : yypt+1] //line sql.y:4441 + { + yyVAL.setExpr = &SetExpr{Name: NewColIdent(string(yyDollar[1].bytes)), Scope: ImplicitScope, Expr: yyDollar[2].expr} + } + case 888: + yyDollar = yyS[yypt-2 : yypt+1] +//line sql.y:4445 { yyDollar[2].setExpr.Scope = yyDollar[1].scope yyVAL.setExpr = yyDollar[2].setExpr } - case 889: + case 890: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4449 +//line sql.y:4453 { yyVAL.bytes = []byte("charset") } - case 892: + case 893: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4459 +//line sql.y:4463 { yyVAL.expr = NewStrLiteral([]byte(yyDollar[1].colIdent.String())) } - case 893: + case 894: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4463 +//line sql.y:4467 { yyVAL.expr = NewStrLiteral(yyDollar[1].bytes) } - case 894: + case 895: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4467 +//line sql.y:4471 { yyVAL.expr = &Default{} } - case 897: + case 898: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4476 +//line sql.y:4480 { yyVAL.boolean = false } - case 898: + case 899: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4478 +//line sql.y:4482 { yyVAL.boolean = true } - case 899: + case 900: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4481 +//line sql.y:4485 { yyVAL.boolean = false } - case 900: + case 901: yyDollar = yyS[yypt-3 : yypt+1] -//line sql.y:4483 +//line sql.y:4487 { yyVAL.boolean = true } - case 901: + case 902: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4486 +//line sql.y:4490 { yyVAL.ignore = false } - case 902: + case 903: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4488 +//line sql.y:4492 { yyVAL.ignore = true } - case 903: + case 904: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4491 +//line sql.y:4495 { yyVAL.empty = struct{}{} } - case 904: + case 905: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4493 +//line sql.y:4497 { yyVAL.empty = struct{}{} } - case 905: + case 906: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4495 +//line sql.y:4499 { yyVAL.empty = struct{}{} } - case 906: + case 907: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4498 +//line sql.y:4502 { yyVAL.str = "" } - case 907: + case 908: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4500 +//line sql.y:4504 { yyVAL.str = string(yyDollar[1].bytes) } - case 908: + case 909: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4502 +//line sql.y:4506 { yyVAL.str = string(yyDollar[1].bytes) } - case 909: + case 910: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4504 +//line sql.y:4508 { yyVAL.str = string(yyDollar[1].bytes) } - case 910: + case 911: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4507 +//line sql.y:4511 { yyVAL.indexOptions = nil } - case 911: + case 912: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4509 +//line sql.y:4513 { yyVAL.indexOptions = []*IndexOption{yyDollar[1].indexOption} } - case 912: + case 913: yyDollar = yyS[yypt-2 : yypt+1] -//line sql.y:4513 +//line sql.y:4517 { yyVAL.indexOption = &IndexOption{Name: string(yyDollar[1].bytes), String: string(yyDollar[2].colIdent.String())} } - case 913: + case 914: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4519 +//line sql.y:4523 { yyVAL.colIdent = yyDollar[1].colIdent } - case 914: + case 915: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4523 +//line sql.y:4527 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 916: + case 917: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4530 +//line sql.y:4534 { yyVAL.colIdent = NewColIdent(string(yyDollar[1].bytes)) } - case 917: + case 918: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4536 +//line sql.y:4540 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].colIdent.String())) } - case 918: + case 919: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4540 +//line sql.y:4544 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 920: + case 921: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4547 +//line sql.y:4551 { yyVAL.tableIdent = NewTableIdent(string(yyDollar[1].bytes)) } - case 1302: + case 1303: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4953 +//line sql.y:4957 { if incNesting(yylex) { yylex.Error("max nesting level reached") return 1 } } - case 1303: + case 1304: yyDollar = yyS[yypt-1 : yypt+1] -//line sql.y:4962 +//line sql.y:4966 { decNesting(yylex) } - case 1304: - yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4967 - { - skipToEnd(yylex) - } case 1305: yyDollar = yyS[yypt-0 : yypt+1] -//line sql.y:4972 +//line sql.y:4971 { skipToEnd(yylex) } case 1306: - yyDollar = yyS[yypt-1 : yypt+1] + yyDollar = yyS[yypt-0 : yypt+1] //line sql.y:4976 { skipToEnd(yylex) @@ -10534,6 +10529,12 @@ yydefault: { skipToEnd(yylex) } + case 1308: + yyDollar = yyS[yypt-1 : yypt+1] +//line sql.y:4984 + { + skipToEnd(yylex) + } } goto yystack /* stack new state and value */ } diff --git a/go/vt/sqlparser/sql.y b/go/vt/sqlparser/sql.y index 9d085188cd4..1ceec18a43e 100644 --- a/go/vt/sqlparser/sql.y +++ b/go/vt/sqlparser/sql.y @@ -3616,47 +3616,51 @@ function_call_keyword: { $$ = &ValuesFuncExpr{Name: $3} } +| CURRENT_USER func_paren_opt + { + $$ = &FuncExpr{Name: NewColIdent(string($1))} + } /* Function calls using non reserved keywords but with special syntax forms. Dedicated grammar rules are needed because of the special syntax */ function_call_nonkeyword: - CURRENT_TIMESTAMP func_datetime_opt + CURRENT_TIMESTAMP func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("current_timestamp")} } -| UTC_TIMESTAMP func_datetime_opt +| UTC_TIMESTAMP func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("utc_timestamp")} } -| UTC_TIME func_datetime_opt +| UTC_TIME func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("utc_time")} } /* doesn't support fsp */ -| UTC_DATE func_datetime_opt +| UTC_DATE func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("utc_date")} } // now -| LOCALTIME func_datetime_opt +| LOCALTIME func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("localtime")} } // now -| LOCALTIMESTAMP func_datetime_opt +| LOCALTIMESTAMP func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("localtimestamp")} } // curdate /* doesn't support fsp */ -| CURRENT_DATE func_datetime_opt +| CURRENT_DATE func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("current_date")} } // curtime -| CURRENT_TIME func_datetime_opt +| CURRENT_TIME func_paren_opt { $$ = &FuncExpr{Name:NewColIdent("current_time")} } @@ -3697,7 +3701,7 @@ function_call_nonkeyword: $$ = &TimestampFuncExpr{Name:string("timestampdiff"), Unit:$3.String(), Expr1:$5, Expr2:$7} } -func_datetime_opt: +func_paren_opt: /* empty */ | openb closeb From e2e4450ade258e3c7a4e8850944eddf16a4eaabe Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 9 Mar 2021 17:37:53 -0800 Subject: [PATCH 12/49] healthcheck: update healthy tablets correctly when a stream returns an error or times out Signed-off-by: deepthi --- go/vt/discovery/healthcheck.go | 29 +++++++++++++------------- go/vt/discovery/healthcheck_test.go | 11 ++++++++++ go/vt/discovery/tablet_health_check.go | 15 +++++++++---- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 02eb035ea21..c672e88ac05 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -404,17 +404,17 @@ func (hc *HealthCheckImpl) deleteTablet(tablet *topodata.Tablet) { } } -func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, shr *query.StreamHealthResponse, currentTarget *query.Target, trivialNonMasterUpdate bool, isMasterUpdate bool, isMasterChange bool) { +func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.Target, trivialNonMasterUpdate bool, isMasterUpdate bool, isMasterChange bool) { // hc.healthByAlias is authoritative, it should be updated hc.mu.Lock() defer hc.mu.Unlock() - tabletAlias := tabletAliasString(topoproto.TabletAliasString(shr.TabletAlias)) - - hcErrorCounters.Add([]string{shr.Target.Keyspace, shr.Target.Shard, topoproto.TabletTypeLString(shr.Target.TabletType)}, 0) - targetKey := hc.keyFromTarget(shr.Target) - targetChanged := currentTarget.TabletType != shr.Target.TabletType || currentTarget.Keyspace != shr.Target.Keyspace || currentTarget.Shard != shr.Target.Shard + tabletAlias := tabletAliasString(topoproto.TabletAliasString(th.Tablet.Alias)) + targetKey := hc.keyFromTarget(th.Target) + targetChanged := currentTarget.TabletType != th.Target.TabletType || currentTarget.Keyspace != th.Target.Keyspace || currentTarget.Shard != th.Target.Shard if targetChanged { + // Error counter has to be set here in case we get a new tablet type for the first time in a stream response + hcErrorCounters.Add([]string{th.Target.Keyspace, th.Target.Shard, topoproto.TabletTypeLString(th.Target.TabletType)}, 0) // keyspace and shard are not expected to change, but just in case ... // move this tabletHealthCheck to the correct map oldTargetKey := hc.keyFromTarget(currentTarget) @@ -433,12 +433,12 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, shr *query.StreamHealt } else { // We already have one up server, see if we // need to replace it. - if shr.TabletExternallyReparentedTimestamp < hc.healthy[targetKey][0].MasterTermStartTime { + if th.MasterTermStartTime < hc.healthy[targetKey][0].MasterTermStartTime { log.Warningf("not marking healthy master %s as Up for %s because its MasterTermStartTime is smaller than the highest known timestamp from previous MASTERs %s: %d < %d ", - topoproto.TabletAliasString(shr.TabletAlias), - topoproto.KeyspaceShardString(shr.Target.Keyspace, shr.Target.Shard), + topoproto.TabletAliasString(th.Tablet.Alias), + topoproto.KeyspaceShardString(th.Target.Keyspace, th.Target.Shard), topoproto.TabletAliasString(hc.healthy[targetKey][0].Tablet.Alias), - shr.TabletExternallyReparentedTimestamp, + th.MasterTermStartTime, hc.healthy[targetKey][0].MasterTermStartTime) } else { // Just replace it. @@ -450,21 +450,20 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, shr *query.StreamHealt // We re-sort the healthy tablet list whenever we get a health update for tablets we can route to. // Tablets from other cells for non-master targets should not trigger a re-sort; // they should also be excluded from healthy list. - if shr.Target.TabletType != topodata.TabletType_MASTER && hc.isIncluded(shr.Target.TabletType, shr.TabletAlias) { + if th.Target.TabletType != topodata.TabletType_MASTER && hc.isIncluded(th.Target.TabletType, th.Tablet.Alias) { hc.recomputeHealthy(targetKey) } - if targetChanged && currentTarget.TabletType != topodata.TabletType_MASTER && hc.isIncluded(shr.Target.TabletType, shr.TabletAlias) { // also recompute old target's healthy list + if targetChanged && currentTarget.TabletType != topodata.TabletType_MASTER && hc.isIncluded(th.Target.TabletType, th.Tablet.Alias) { // also recompute old target's healthy list oldTargetKey := hc.keyFromTarget(currentTarget) hc.recomputeHealthy(oldTargetKey) } } if isMasterChange { - log.Errorf("Adding 1 to MasterPromoted counter for tablet: %v, shr.Tablet: %v, shr.TabletType: %v", currentTarget, topoproto.TabletAliasString(shr.TabletAlias), shr.Target.TabletType) - hcMasterPromotedCounters.Add([]string{shr.Target.Keyspace, shr.Target.Shard}, 1) + log.Errorf("Adding 1 to MasterPromoted counter for target: %v, tablet: %v, tabletType: %v", currentTarget, topoproto.TabletAliasString(th.Tablet.Alias), th.Target.TabletType) + hcMasterPromotedCounters.Add([]string{th.Target.Keyspace, th.Target.Shard}, 1) } // broadcast to subscribers hc.broadcast(th) - } func (hc *HealthCheckImpl) recomputeHealthy(key keyspaceShardTabletType) { diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index e2b4d125f29..3b4046b58b5 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -65,6 +65,8 @@ func init() { } func TestHealthCheck(t *testing.T) { + // reset error counters + hcErrorCounters.ResetAll() ts := memorytopo.NewServer("cell") hc := createTestHc(ts) // close healthcheck @@ -257,6 +259,9 @@ func TestHealthCheckStreamError(t *testing.T) { result = <-resultChan //TODO: figure out how to compare objects that contain errors using utils.MustMatch assert.True(t, want.DeepEqual(result), "Wrong TabletHealth data\n Expected: %v\n Actual: %v", want, result) + // tablet should be removed from healthy list + a := hc.GetHealthyTabletStats(&querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}) + assert.Empty(t, a, "wrong result, expected empty list") } func TestHealthCheckVerifiesTabletAlias(t *testing.T) { @@ -363,6 +368,8 @@ func TestHealthCheckCloseWaitsForGoRoutines(t *testing.T) { } func TestHealthCheckTimeout(t *testing.T) { + // reset counters + hcErrorCounters.ResetAll() ts := memorytopo.NewServer("cell") hc := createTestHc(ts) hc.healthCheckTimeout = 500 * time.Millisecond @@ -410,6 +417,10 @@ func TestHealthCheckTimeout(t *testing.T) { assert.Nil(t, checkErrorCounter("k", "s", topodatapb.TabletType_REPLICA, 1)) assert.True(t, fc.isCanceled(), "StreamHealth should be canceled after timeout, but is not") + // tablet should be removed from healthy list + a := hc.GetHealthyTabletStats(&querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_REPLICA}) + assert.Empty(t, a, "wrong result, expected empty list") + // repeat the wait. It will timeout one more time trying to get the connection. fc.resetCanceledFlag() time.Sleep(hc.healthCheckTimeout) diff --git a/go/vt/discovery/tablet_health_check.go b/go/vt/discovery/tablet_health_check.go index 4882ac39341..2f36f78e765 100644 --- a/go/vt/discovery/tablet_health_check.go +++ b/go/vt/discovery/tablet_health_check.go @@ -202,7 +202,7 @@ func (thc *tabletHealthCheck) processResponse(hc *HealthCheckImpl, shr *query.St thc.setServingState(serving, reason) // notify downstream for master change - hc.updateHealth(thc.SimpleCopy(), shr, currentTarget, trivialNonMasterUpdate, isMasterUpdate, isMasterChange) + hc.updateHealth(thc.SimpleCopy(), currentTarget, trivialNonMasterUpdate, isMasterUpdate, isMasterChange) return nil } @@ -241,6 +241,9 @@ func (thc *tabletHealthCheck) checkConn(hc *HealthCheckImpl) { hc.connsWG.Done() }() + // Initialize error counter + hcErrorCounters.Add([]string{thc.Target.Keyspace, thc.Target.Shard, topoproto.TabletTypeLString(thc.Target.TabletType)}, 0) + retryDelay := hc.retryDelay for { streamCtx, streamCancel := context.WithCancel(thc.ctx) @@ -287,12 +290,14 @@ func (thc *tabletHealthCheck) checkConn(hc *HealthCheckImpl) { streamCancel() if err != nil { + hcErrorCounters.Add([]string{thc.Target.Keyspace, thc.Target.Shard, topoproto.TabletTypeLString(thc.Target.TabletType)}, 1) if strings.Contains(err.Error(), "health stats mismatch") { hc.deleteTablet(thc.Tablet) return } - res := thc.SimpleCopy() - hc.broadcast(res) + // trivialNonMasterUpdate = false because this is an error + // It is safe to pass isMasterChange = false because in case of an error there is no information that can be used to update the master + hc.updateHealth(thc.SimpleCopy(), thc.Target, false, thc.Target.TabletType == topodata.TabletType_MASTER, false) } // If there was a timeout send an error. We do this after stream has returned. // This will ensure that this update prevails over any previous message that @@ -301,7 +306,9 @@ func (thc *tabletHealthCheck) checkConn(hc *HealthCheckImpl) { thc.LastError = fmt.Errorf("healthcheck timed out (latest %v)", thc.lastResponseTimestamp) thc.setServingState(false, thc.LastError.Error()) hcErrorCounters.Add([]string{thc.Target.Keyspace, thc.Target.Shard, topoproto.TabletTypeLString(thc.Target.TabletType)}, 1) - hc.broadcast(thc.SimpleCopy()) + // trivialNonMasterUpdate = false because this is an error + // It is safe to pass isMasterChange = false because in case of timeout there is no information that can be used to update the master + hc.updateHealth(thc.SimpleCopy(), thc.Target, false, thc.Target.TabletType == topodata.TabletType_MASTER, false) } // Streaming RPC failed e.g. because vttablet was restarted or took too long. From a83d30e481e2ac7d004cbeac2fa89b2c63b4cf4d Mon Sep 17 00:00:00 2001 From: deepthi Date: Wed, 10 Mar 2021 17:34:38 -0800 Subject: [PATCH 13/49] healthcheck: remove PRIMARY from healthy list when there's an error or timeout from healthcheck stream Signed-off-by: deepthi --- go/vt/discovery/healthcheck.go | 41 ++++++++++-------- go/vt/discovery/healthcheck_test.go | 60 ++++++++++++++++++++++++++ go/vt/discovery/tablet_health_check.go | 18 ++++---- 3 files changed, 91 insertions(+), 28 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index c672e88ac05..f091a13a441 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -404,7 +404,7 @@ func (hc *HealthCheckImpl) deleteTablet(tablet *topodata.Tablet) { } } -func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.Target, trivialNonMasterUpdate bool, isMasterUpdate bool, isMasterChange bool) { +func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.Target, trivialUpdate bool, isPrimaryUp bool) { // hc.healthByAlias is authoritative, it should be updated hc.mu.Lock() defer hc.mu.Unlock() @@ -427,26 +427,31 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.T // add it to the map by target hc.healthData[targetKey][tabletAlias] = th - if isMasterUpdate { - if len(hc.healthy[targetKey]) == 0 { - hc.healthy[targetKey] = append(hc.healthy[targetKey], th) - } else { - // We already have one up server, see if we - // need to replace it. - if th.MasterTermStartTime < hc.healthy[targetKey][0].MasterTermStartTime { - log.Warningf("not marking healthy master %s as Up for %s because its MasterTermStartTime is smaller than the highest known timestamp from previous MASTERs %s: %d < %d ", - topoproto.TabletAliasString(th.Tablet.Alias), - topoproto.KeyspaceShardString(th.Target.Keyspace, th.Target.Shard), - topoproto.TabletAliasString(hc.healthy[targetKey][0].Tablet.Alias), - th.MasterTermStartTime, - hc.healthy[targetKey][0].MasterTermStartTime) + if th.Target.TabletType == topodata.TabletType_MASTER { + if isPrimaryUp { + if len(hc.healthy[targetKey]) == 0 { + hc.healthy[targetKey] = append(hc.healthy[targetKey], th) } else { - // Just replace it. - hc.healthy[targetKey][0] = th + // We already have one up server, see if we + // need to replace it. + if th.MasterTermStartTime < hc.healthy[targetKey][0].MasterTermStartTime { + log.Warningf("not marking healthy master %s as Up for %s because its MasterTermStartTime is smaller than the highest known timestamp from previous MASTERs %s: %d < %d ", + topoproto.TabletAliasString(th.Tablet.Alias), + topoproto.KeyspaceShardString(th.Target.Keyspace, th.Target.Shard), + topoproto.TabletAliasString(hc.healthy[targetKey][0].Tablet.Alias), + th.MasterTermStartTime, + hc.healthy[targetKey][0].MasterTermStartTime) + } else { + // Just replace it. + hc.healthy[targetKey][0] = th + } } + } else { + // No healthy master tablet + hc.healthy[targetKey] = []*TabletHealth{} } } - if !trivialNonMasterUpdate { + if !trivialUpdate { // We re-sort the healthy tablet list whenever we get a health update for tablets we can route to. // Tablets from other cells for non-master targets should not trigger a re-sort; // they should also be excluded from healthy list. @@ -458,7 +463,7 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.T hc.recomputeHealthy(oldTargetKey) } } - if isMasterChange { + if currentTarget.TabletType != topodata.TabletType_MASTER && th.Target.TabletType == topodata.TabletType_MASTER { log.Errorf("Adding 1 to MasterPromoted counter for target: %v, tablet: %v, tabletType: %v", currentTarget, topoproto.TabletAliasString(th.Tablet.Alias), th.Target.TabletType) hcMasterPromotedCounters.Add([]string{th.Target.Keyspace, th.Target.Shard}, 1) } diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index 3b4046b58b5..2d554ab2cf2 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -264,6 +264,66 @@ func TestHealthCheckStreamError(t *testing.T) { assert.Empty(t, a, "wrong result, expected empty list") } +// TestHealthCheckErrorOnPrimary is the same as TestHealthCheckStreamError except for tablet type +func TestHealthCheckErrorOnPrimary(t *testing.T) { + ts := memorytopo.NewServer("cell") + hc := createTestHc(ts) + defer hc.Close() + + tablet := createTestTablet(0, "cell", "a") + input := make(chan *querypb.StreamHealthResponse) + resultChan := hc.Subscribe() + fc := createFakeConn(tablet, input) + fc.errCh = make(chan error) + hc.AddTablet(tablet) + + // Immediately after AddTablet() there will be the first notification. + want := &TabletHealth{ + Tablet: tablet, + Target: &querypb.Target{Keyspace: "k", Shard: "s"}, + Serving: false, + MasterTermStartTime: 0, + } + result := <-resultChan + mustMatch(t, want, result, "Wrong TabletHealth data") + + // one tablet after receiving a StreamHealthResponse + shr := &querypb.StreamHealthResponse{ + TabletAlias: tablet.Alias, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_MASTER}, + Serving: true, + TabletExternallyReparentedTimestamp: 10, + RealtimeStats: &querypb.RealtimeStats{SecondsBehindMaster: 1, CpuUsage: 0.2}, + } + want = &TabletHealth{ + Tablet: tablet, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_MASTER}, + Serving: true, + Stats: &querypb.RealtimeStats{SecondsBehindMaster: 1, CpuUsage: 0.2}, + MasterTermStartTime: 10, + } + input <- shr + result = <-resultChan + mustMatch(t, want, result, "Wrong TabletHealth data") + + // Stream error + fc.errCh <- fmt.Errorf("some stream error") + want = &TabletHealth{ + Tablet: tablet, + Target: &querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_MASTER}, + Serving: false, + Stats: &querypb.RealtimeStats{SecondsBehindMaster: 1, CpuUsage: 0.2}, + MasterTermStartTime: 10, + LastError: fmt.Errorf("some stream error"), + } + result = <-resultChan + //TODO: figure out how to compare objects that contain errors using utils.MustMatch + assert.True(t, want.DeepEqual(result), "Wrong TabletHealth data\n Expected: %v\n Actual: %v", want, result) + // tablet should be removed from healthy list + a := hc.GetHealthyTabletStats(&querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_MASTER}) + assert.Empty(t, a, "wrong result, expected empty list") +} + func TestHealthCheckVerifiesTabletAlias(t *testing.T) { ts := memorytopo.NewServer("cell") hc := createTestHc(ts) diff --git a/go/vt/discovery/tablet_health_check.go b/go/vt/discovery/tablet_health_check.go index 2f36f78e765..c008d2f162f 100644 --- a/go/vt/discovery/tablet_health_check.go +++ b/go/vt/discovery/tablet_health_check.go @@ -186,10 +186,8 @@ func (thc *tabletHealthCheck) processResponse(hc *HealthCheckImpl, shr *query.St currentTarget := thc.Target // check whether this is a trivial update so as to update healthy map - trivialNonMasterUpdate := thc.LastError == nil && thc.Serving && shr.RealtimeStats.HealthError == "" && shr.Serving && + trivialUpdate := thc.LastError == nil && thc.Serving && shr.RealtimeStats.HealthError == "" && shr.Serving && currentTarget.TabletType != topodata.TabletType_MASTER && currentTarget.TabletType == shr.Target.TabletType && thc.isTrivialReplagChange(shr.RealtimeStats) - isMasterUpdate := shr.Target.TabletType == topodata.TabletType_MASTER - isMasterChange := thc.Target.TabletType != topodata.TabletType_MASTER && shr.Target.TabletType == topodata.TabletType_MASTER thc.lastResponseTimestamp = time.Now() thc.Target = shr.Target thc.MasterTermStartTime = shr.TabletExternallyReparentedTimestamp @@ -202,7 +200,7 @@ func (thc *tabletHealthCheck) processResponse(hc *HealthCheckImpl, shr *query.St thc.setServingState(serving, reason) // notify downstream for master change - hc.updateHealth(thc.SimpleCopy(), currentTarget, trivialNonMasterUpdate, isMasterUpdate, isMasterChange) + hc.updateHealth(thc.SimpleCopy(), currentTarget, trivialUpdate, true) return nil } @@ -295,9 +293,9 @@ func (thc *tabletHealthCheck) checkConn(hc *HealthCheckImpl) { hc.deleteTablet(thc.Tablet) return } - // trivialNonMasterUpdate = false because this is an error - // It is safe to pass isMasterChange = false because in case of an error there is no information that can be used to update the master - hc.updateHealth(thc.SimpleCopy(), thc.Target, false, thc.Target.TabletType == topodata.TabletType_MASTER, false) + // trivialUpdate = false because this is an error + // isPrimaryUp = false because we did not get a healthy response + hc.updateHealth(thc.SimpleCopy(), thc.Target, false, false) } // If there was a timeout send an error. We do this after stream has returned. // This will ensure that this update prevails over any previous message that @@ -306,9 +304,9 @@ func (thc *tabletHealthCheck) checkConn(hc *HealthCheckImpl) { thc.LastError = fmt.Errorf("healthcheck timed out (latest %v)", thc.lastResponseTimestamp) thc.setServingState(false, thc.LastError.Error()) hcErrorCounters.Add([]string{thc.Target.Keyspace, thc.Target.Shard, topoproto.TabletTypeLString(thc.Target.TabletType)}, 1) - // trivialNonMasterUpdate = false because this is an error - // It is safe to pass isMasterChange = false because in case of timeout there is no information that can be used to update the master - hc.updateHealth(thc.SimpleCopy(), thc.Target, false, thc.Target.TabletType == topodata.TabletType_MASTER, false) + // trivialUpdate = false because this is an error + // isPrimaryUp = false because we did not get a healthy response within the timeout + hc.updateHealth(thc.SimpleCopy(), thc.Target, false, false) } // Streaming RPC failed e.g. because vttablet was restarted or took too long. From c3693f85c7aa1f9e70981a00e7d14d71b4cb3aa1 Mon Sep 17 00:00:00 2001 From: deepthi Date: Thu, 11 Mar 2021 17:35:43 -0800 Subject: [PATCH 14/49] healthcheck: reorganize code to be more readable Signed-off-by: deepthi --- go/vt/discovery/healthcheck.go | 58 ++++++++++++++------------ go/vt/discovery/healthcheck_test.go | 2 +- go/vt/discovery/tablet_health_check.go | 6 +-- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index f091a13a441..4af9dfd7202 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -404,20 +404,20 @@ func (hc *HealthCheckImpl) deleteTablet(tablet *topodata.Tablet) { } } -func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.Target, trivialUpdate bool, isPrimaryUp bool) { +func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, prevTarget *query.Target, trivialUpdate bool, isPrimaryUp bool) { // hc.healthByAlias is authoritative, it should be updated hc.mu.Lock() defer hc.mu.Unlock() tabletAlias := tabletAliasString(topoproto.TabletAliasString(th.Tablet.Alias)) targetKey := hc.keyFromTarget(th.Target) - targetChanged := currentTarget.TabletType != th.Target.TabletType || currentTarget.Keyspace != th.Target.Keyspace || currentTarget.Shard != th.Target.Shard + targetChanged := prevTarget.TabletType != th.Target.TabletType || prevTarget.Keyspace != th.Target.Keyspace || prevTarget.Shard != th.Target.Shard if targetChanged { // Error counter has to be set here in case we get a new tablet type for the first time in a stream response hcErrorCounters.Add([]string{th.Target.Keyspace, th.Target.Shard, topoproto.TabletTypeLString(th.Target.TabletType)}, 0) // keyspace and shard are not expected to change, but just in case ... // move this tabletHealthCheck to the correct map - oldTargetKey := hc.keyFromTarget(currentTarget) + oldTargetKey := hc.keyFromTarget(prevTarget) delete(hc.healthData[oldTargetKey], tabletAlias) _, ok := hc.healthData[targetKey] if !ok { @@ -427,30 +427,31 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.T // add it to the map by target hc.healthData[targetKey][tabletAlias] = th - if th.Target.TabletType == topodata.TabletType_MASTER { - if isPrimaryUp { - if len(hc.healthy[targetKey]) == 0 { - hc.healthy[targetKey] = append(hc.healthy[targetKey], th) + isPrimary := th.Target.TabletType == topodata.TabletType_MASTER + switch { + case isPrimary && isPrimaryUp: + if len(hc.healthy[targetKey]) == 0 { + hc.healthy[targetKey] = append(hc.healthy[targetKey], th) + } else { + // We already have one up server, see if we + // need to replace it. + if th.MasterTermStartTime < hc.healthy[targetKey][0].MasterTermStartTime { + log.Warningf("not marking healthy master %s as Up for %s because its MasterTermStartTime is smaller than the highest known timestamp from previous MASTERs %s: %d < %d ", + topoproto.TabletAliasString(th.Tablet.Alias), + topoproto.KeyspaceShardString(th.Target.Keyspace, th.Target.Shard), + topoproto.TabletAliasString(hc.healthy[targetKey][0].Tablet.Alias), + th.MasterTermStartTime, + hc.healthy[targetKey][0].MasterTermStartTime) } else { - // We already have one up server, see if we - // need to replace it. - if th.MasterTermStartTime < hc.healthy[targetKey][0].MasterTermStartTime { - log.Warningf("not marking healthy master %s as Up for %s because its MasterTermStartTime is smaller than the highest known timestamp from previous MASTERs %s: %d < %d ", - topoproto.TabletAliasString(th.Tablet.Alias), - topoproto.KeyspaceShardString(th.Target.Keyspace, th.Target.Shard), - topoproto.TabletAliasString(hc.healthy[targetKey][0].Tablet.Alias), - th.MasterTermStartTime, - hc.healthy[targetKey][0].MasterTermStartTime) - } else { - // Just replace it. - hc.healthy[targetKey][0] = th - } + // Just replace it. + hc.healthy[targetKey][0] = th } - } else { - // No healthy master tablet - hc.healthy[targetKey] = []*TabletHealth{} } + case isPrimary && !isPrimaryUp: + // No healthy master tablet + hc.healthy[targetKey] = []*TabletHealth{} } + if !trivialUpdate { // We re-sort the healthy tablet list whenever we get a health update for tablets we can route to. // Tablets from other cells for non-master targets should not trigger a re-sort; @@ -458,15 +459,18 @@ func (hc *HealthCheckImpl) updateHealth(th *TabletHealth, currentTarget *query.T if th.Target.TabletType != topodata.TabletType_MASTER && hc.isIncluded(th.Target.TabletType, th.Tablet.Alias) { hc.recomputeHealthy(targetKey) } - if targetChanged && currentTarget.TabletType != topodata.TabletType_MASTER && hc.isIncluded(th.Target.TabletType, th.Tablet.Alias) { // also recompute old target's healthy list - oldTargetKey := hc.keyFromTarget(currentTarget) + if targetChanged && prevTarget.TabletType != topodata.TabletType_MASTER && hc.isIncluded(th.Target.TabletType, th.Tablet.Alias) { // also recompute old target's healthy list + oldTargetKey := hc.keyFromTarget(prevTarget) hc.recomputeHealthy(oldTargetKey) } } - if currentTarget.TabletType != topodata.TabletType_MASTER && th.Target.TabletType == topodata.TabletType_MASTER { - log.Errorf("Adding 1 to MasterPromoted counter for target: %v, tablet: %v, tabletType: %v", currentTarget, topoproto.TabletAliasString(th.Tablet.Alias), th.Target.TabletType) + + isNewPrimary := isPrimary && prevTarget.TabletType != topodata.TabletType_MASTER + if isNewPrimary { + log.Errorf("Adding 1 to MasterPromoted counter for target: %v, tablet: %v, tabletType: %v", prevTarget, topoproto.TabletAliasString(th.Tablet.Alias), th.Target.TabletType) hcMasterPromotedCounters.Add([]string{th.Target.Keyspace, th.Target.Shard}, 1) } + // broadcast to subscribers hc.broadcast(th) } diff --git a/go/vt/discovery/healthcheck_test.go b/go/vt/discovery/healthcheck_test.go index 2d554ab2cf2..73ba30a665f 100644 --- a/go/vt/discovery/healthcheck_test.go +++ b/go/vt/discovery/healthcheck_test.go @@ -869,7 +869,7 @@ func TestMasterInOtherCell(t *testing.T) { // check that MASTER tablet from other cell IS in healthy tablet list a := hc.GetHealthyTabletStats(&querypb.Target{Keyspace: "k", Shard: "s", TabletType: topodatapb.TabletType_MASTER}) - assert.Len(t, a, 1, "") + require.Len(t, a, 1, "") mustMatch(t, want, a[0], "Expecting healthy master") } diff --git a/go/vt/discovery/tablet_health_check.go b/go/vt/discovery/tablet_health_check.go index c008d2f162f..664e1924870 100644 --- a/go/vt/discovery/tablet_health_check.go +++ b/go/vt/discovery/tablet_health_check.go @@ -184,10 +184,10 @@ func (thc *tabletHealthCheck) processResponse(hc *HealthCheckImpl, shr *query.St return vterrors.New(vtrpc.Code_FAILED_PRECONDITION, fmt.Sprintf("health stats mismatch, tablet %+v alias does not match response alias %v", thc.Tablet, shr.TabletAlias)) } - currentTarget := thc.Target + prevTarget := thc.Target // check whether this is a trivial update so as to update healthy map trivialUpdate := thc.LastError == nil && thc.Serving && shr.RealtimeStats.HealthError == "" && shr.Serving && - currentTarget.TabletType != topodata.TabletType_MASTER && currentTarget.TabletType == shr.Target.TabletType && thc.isTrivialReplagChange(shr.RealtimeStats) + prevTarget.TabletType != topodata.TabletType_MASTER && prevTarget.TabletType == shr.Target.TabletType && thc.isTrivialReplagChange(shr.RealtimeStats) thc.lastResponseTimestamp = time.Now() thc.Target = shr.Target thc.MasterTermStartTime = shr.TabletExternallyReparentedTimestamp @@ -200,7 +200,7 @@ func (thc *tabletHealthCheck) processResponse(hc *HealthCheckImpl, shr *query.St thc.setServingState(serving, reason) // notify downstream for master change - hc.updateHealth(thc.SimpleCopy(), currentTarget, trivialUpdate, true) + hc.updateHealth(thc.SimpleCopy(), prevTarget, trivialUpdate, true) return nil } From c343360f4dbf159f06d81cd0618e64adc6d7281b Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Tue, 23 Mar 2021 15:02:11 +0100 Subject: [PATCH 15/49] make sure to handle subqueries on top of subqueries Signed-off-by: Andres Taylor Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/misc_test.go | 14 ++++++ .../multi-output/selectsharded-output.txt | 6 +++ .../testdata/selectsharded-queries.sql | 2 + go/vt/vtgate/planbuilder/filtering.go | 4 +- .../planbuilder/testdata/filter_cases.txt | 47 ++++++++++++++----- 5 files changed, 59 insertions(+), 14 deletions(-) diff --git a/go/test/endtoend/vtgate/misc_test.go b/go/test/endtoend/vtgate/misc_test.go index 415d67a2840..09a075556ae 100644 --- a/go/test/endtoend/vtgate/misc_test.go +++ b/go/test/endtoend/vtgate/misc_test.go @@ -496,6 +496,20 @@ func TestCreateView(t *testing.T) { assertMatches(t, conn, "select * from v1", `[[INT64(1) INT64(1)] [INT64(2) INT64(2)] [INT64(3) INT64(3)] [INT64(4) INT64(4)] [INT64(5) INT64(5)]]`) } +func TestSubQueryOnTopOfSubQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + defer exec(t, conn, `delete from t1`) + + exec(t, conn, `insert into t1(id1, id2) values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)`) + exec(t, conn, `insert into t2(id3, id4) values (1, 3), (2, 4)`) + + assertMatches(t, conn, "select id1 from t1 where id1 not in (select id3 from t2) and id2 in (select id4 from t2)", `[[INT64(3)] [INT64(4)]]`) +} + func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { t.Helper() qr := exec(t, conn, query) diff --git a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt index ccad1126651..f17fa13e4cc 100644 --- a/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt +++ b/go/vt/vtexplain/testdata/multi-output/selectsharded-output.txt @@ -166,3 +166,9 @@ select id, 'abc' as test from user where id = 1 union all select id, 'def' as te 1 ks_sharded/-40: select id, 'abc' as test from user where id = 1 union all select id, 'def' as test from user where id = 1 union all select id, 'ghi' as test from user where id = 1 limit 10001 /* union all */ ---------------------------------------------------------------------- +select id from user where not id in (select col from music where music.user_id = 42) and id in (select col from music where music.user_id = 411) + +1 ks_sharded/40-80: select col from music where music.user_id = 42 limit 10001 +2 ks_sharded/40-80: select col from music where music.user_id = 411 limit 10001 + +---------------------------------------------------------------------- diff --git a/go/vt/vtexplain/testdata/selectsharded-queries.sql b/go/vt/vtexplain/testdata/selectsharded-queries.sql index e2fdfc3171e..a32e1a6cd21 100644 --- a/go/vt/vtexplain/testdata/selectsharded-queries.sql +++ b/go/vt/vtexplain/testdata/selectsharded-queries.sql @@ -32,3 +32,5 @@ select id, case when name = 'alice' then 'ALICE' when name = 'bob' then 'BOB' el select id, case when substr(name, 1, 5) = 'alice' then 'ALICE' when name = 'bob' then 'BOB' else 'OTHER' end as name from user where id = 1 /* select case */; select id, 'abc' as test from user where id = 1 union all select id, 'def' as test from user where id = 1 union all select id, 'ghi' as test from user where id = 1 /* union all */; + +select id from user where not id in (select col from music where music.user_id = 42) and id in (select col from music where music.user_id = 411); diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index 4e22a3cdbc6..1e085f09ca6 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -64,7 +64,9 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, node.UpdatePlan(pb, filter) return node, nil case *pulloutSubquery: - return planFilter(pb, node.underlying, filter, whereType, origin) + plan, err := planFilter(pb, node.underlying, filter, whereType, origin) + node.underlying = plan + return node, err case *vindexFunc: return filterVindexFunc(node, filter) case *subquery: diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index 038e498bc60..a2ba4862a31 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1799,19 +1799,40 @@ "Vindex": "user_index" }, { - "OperatorType": "Route", - "Variant": "SelectIN", - "Keyspace": { - "Name": "user", - "Sharded": true - }, - "FieldQuery": "select id from user where 1 != 1", - "Query": "select id from user where :__sq_has_values1 = 1 and id in ::__vals and not (:__sq_has_values2 = 1 and id in ::__sq2)", - "Table": "user", - "Values": [ - "::__sq1" - ], - "Vindex": "user_index" + "OperatorType": "Subquery", + "Variant": "PulloutIn", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectEqualUnique", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select user_extra.col from user_extra where 1 != 1", + "Query": "select user_extra.col from user_extra where user_extra.user_id = 411", + "Table": "user_extra", + "Values": [ + 411 + ], + "Vindex": "user_index" + }, + { + "OperatorType": "Route", + "Variant": "SelectIN", + "Keyspace": { + "Name": "user", + "Sharded": true + }, + "FieldQuery": "select id from user where 1 != 1", + "Query": "select id from user where :__sq_has_values1 = 1 and id in ::__vals and not (:__sq_has_values2 = 1 and id in ::__sq2)", + "Table": "user", + "Values": [ + "::__sq1" + ], + "Vindex": "user_index" + } + ] } ] } From 61e13d2728b6959496b9bec521957e79e136ce38 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 25 Mar 2021 14:31:16 +0100 Subject: [PATCH 16/49] check error before returning Signed-off-by: Andres Taylor --- go/vt/vtgate/planbuilder/filtering.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/go/vt/vtgate/planbuilder/filtering.go b/go/vt/vtgate/planbuilder/filtering.go index 1e085f09ca6..6b442a2f169 100644 --- a/go/vt/vtgate/planbuilder/filtering.go +++ b/go/vt/vtgate/planbuilder/filtering.go @@ -65,8 +65,11 @@ func planFilter(pb *primitiveBuilder, input logicalPlan, filter sqlparser.Expr, return node, nil case *pulloutSubquery: plan, err := planFilter(pb, node.underlying, filter, whereType, origin) + if err != nil { + return nil, err + } node.underlying = plan - return node, err + return node, nil case *vindexFunc: return filterVindexFunc(node, filter) case *subquery: From ca705e6f454beca42ef2376ad792d37b93fee7a9 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 1 Apr 2021 08:23:20 +0200 Subject: [PATCH 17/49] make sure to not log sensitive information Signed-off-by: Andres Taylor --- go/vt/vtgate/executor.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index dec82d79380..994e28386c4 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -157,7 +157,11 @@ func (e *Executor) Execute(ctx context.Context, method string, safeSession *Safe saveSessionStats(safeSession, stmtType, result, err) if result != nil && len(result.Rows) > *warnMemoryRows { warnings.Add("ResultsExceeded", 1) - log.Warningf("%q exceeds warning threshold of max memory rows: %v", sql, *warnMemoryRows) + piiSafeSQL, err := sqlparser.RedactSQLQuery(sql) + if err != nil { + piiSafeSQL = sqlparser.Preview(sql).String() + } + log.Warningf("%q exceeds warning threshold of max memory rows: %v", piiSafeSQL, *warnMemoryRows) } logStats.Send() From b720ad09200eba5430caab8a0e9bcb75296575ca Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 1 Apr 2021 15:27:00 +0530 Subject: [PATCH 18/49] addressed review comments Signed-off-by: Harshit Gangal --- go/vt/vtgate/executor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/vt/vtgate/executor.go b/go/vt/vtgate/executor.go index 994e28386c4..6a23241d200 100644 --- a/go/vt/vtgate/executor.go +++ b/go/vt/vtgate/executor.go @@ -159,7 +159,7 @@ func (e *Executor) Execute(ctx context.Context, method string, safeSession *Safe warnings.Add("ResultsExceeded", 1) piiSafeSQL, err := sqlparser.RedactSQLQuery(sql) if err != nil { - piiSafeSQL = sqlparser.Preview(sql).String() + piiSafeSQL = logStats.StmtType } log.Warningf("%q exceeds warning threshold of max memory rows: %v", piiSafeSQL, *warnMemoryRows) } From 2e35451769ae4f00d9aeb0f08278a3e63ed16648 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Sat, 1 May 2021 12:23:18 +0530 Subject: [PATCH 19/49] ddl bypass planner Signed-off-by: Harshit Gangal Signed-off-by: Rafael Chacon --- go/vt/vtgate/planbuilder/ddl.go | 15 +++++++++++++++ .../planbuilder/testdata/bypass_cases.txt | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go index 77873b3abbe..d61a8997ced 100644 --- a/go/vt/vtgate/planbuilder/ddl.go +++ b/go/vt/vtgate/planbuilder/ddl.go @@ -25,6 +25,9 @@ const ( // and which chooses which of the two to invoke at runtime. func buildGeneralDDLPlan(sql string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (engine.Primitive, error) { normalDDLPlan, onlineDDLPlan, err := buildDDLPlans(sql, ddlStatement, vschema) + if vschema.Destination() != nil { + return buildByPassDDLPlan(sql, vschema) + } if err != nil { return nil, err } @@ -38,6 +41,18 @@ func buildGeneralDDLPlan(sql string, ddlStatement sqlparser.DDLStatement, vschem }, nil } +func buildByPassDDLPlan(sql string, vschema ContextVSchema) (engine.Primitive, error) { + keyspace, err := vschema.DefaultKeyspace() + if err != nil { + return nil, err + } + return &engine.Send{ + Keyspace: keyspace, + TargetDestination: vschema.Destination(), + Query: sql, + }, nil +} + func buildDDLPlans(sql string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (*engine.Send, *engine.OnlineDDL, error) { var destination key.Destination var keyspace *vindexes.Keyspace diff --git a/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt b/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt index daafda9d360..7bb0fc36af5 100644 --- a/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/bypass_cases.txt @@ -156,3 +156,21 @@ "SingleShardOnly": true } } + +# create table +"create /* test */ table t1(id bigint, primary key(id)) /* comments */" +{ + "QueryType": "DDL", + "Original": "create /* test */ table t1(id bigint, primary key(id)) /* comments */", + "Instructions": { + "OperatorType": "Send", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "TargetDestination": "Shard(-80)", + "IsDML": false, + "Query": "create /* test */ table t1(id bigint, primary key(id)) /* comments */", + "SingleShardOnly": false + } +} From 5501139822e1a166a889765f89ae5cfa9cf261d2 Mon Sep 17 00:00:00 2001 From: Rafael Chacon Date: Tue, 4 May 2021 22:40:26 -0700 Subject: [PATCH 20/49] Fixes bad conflict resolution Signed-off-by: Rafael Chacon --- go/vt/vtgate/planbuilder/ddl.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go/vt/vtgate/planbuilder/ddl.go b/go/vt/vtgate/planbuilder/ddl.go index d61a8997ced..f0627c8723c 100644 --- a/go/vt/vtgate/planbuilder/ddl.go +++ b/go/vt/vtgate/planbuilder/ddl.go @@ -24,10 +24,11 @@ const ( // This is why we return a compound primitive (DDL) which contains fully populated primitives (Send & OnlineDDL), // and which chooses which of the two to invoke at runtime. func buildGeneralDDLPlan(sql string, ddlStatement sqlparser.DDLStatement, vschema ContextVSchema) (engine.Primitive, error) { - normalDDLPlan, onlineDDLPlan, err := buildDDLPlans(sql, ddlStatement, vschema) if vschema.Destination() != nil { return buildByPassDDLPlan(sql, vschema) } + + normalDDLPlan, onlineDDLPlan, err := buildDDLPlans(sql, ddlStatement, vschema) if err != nil { return nil, err } From be3ce273d465d0023d4cb50d76c3ba48971849de Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 5 May 2021 11:15:53 +0530 Subject: [PATCH 21/49] merge sort stream fix Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/merge_sort.go | 5 ++-- go/vt/vtgate/executor_select_test.go | 36 +++++++++++++++++++++++ go/vt/vttablet/sandboxconn/sandboxconn.go | 18 ++++++++++-- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/go/vt/vtgate/engine/merge_sort.go b/go/vt/vtgate/engine/merge_sort.go index 6aa01e4d4d4..59d3c1ab3bb 100644 --- a/go/vt/vtgate/engine/merge_sort.go +++ b/go/vt/vtgate/engine/merge_sort.go @@ -81,7 +81,7 @@ func (ms *MergeSort) StreamExecute(vcursor VCursor, bindVars map[string]*querypb handles := make([]*streamHandle, len(ms.Primitives)) for i, input := range ms.Primitives { - handles[i] = runOneStream(vcursor, input, bindVars, wantfields) + handles[i] = runOneStream(ctx, vcursor, input, bindVars, wantfields) // Need fields only from first handle, if wantfields was true. wantfields = false } @@ -183,12 +183,11 @@ type streamHandle struct { } // runOnestream starts a streaming query on one shard, and returns a streamHandle for it. -func runOneStream(vcursor VCursor, input StreamExecutor, bindVars map[string]*querypb.BindVariable, wantfields bool) *streamHandle { +func runOneStream(ctx context.Context, vcursor VCursor, input StreamExecutor, bindVars map[string]*querypb.BindVariable, wantfields bool) *streamHandle { handle := &streamHandle{ fields: make(chan []*querypb.Field, 1), row: make(chan []sqltypes.Value, 10), } - ctx := vcursor.Context() go func() { defer close(handle.fields) diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index d5783b070ce..50eab386464 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -19,8 +19,10 @@ package vtgate import ( "fmt" "reflect" + "runtime" "strings" "testing" + "time" "vitess.io/vitess/go/test/utils" @@ -2420,3 +2422,37 @@ func TestSelectFromInformationSchema(t *testing.T) { require.NoError(t, err) assert.Equal(t, sbc1.StringQueries(), []string{"select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname"}) } + +func TestStreamOrderByLimitWithMultipleResults(t *testing.T) { + // Special setup: Don't use createLegacyExecutorEnv. + cell := "aa" + hc := discovery.NewFakeHealthCheck() + s := createSandbox("TestExecutor") + s.VSchema = executorVSchema + getSandbox(KsTestUnsharded).VSchema = unshardedVSchema + serv := new(sandboxTopo) + resolver := newTestResolver(hc, serv, cell) + shards := []string{"-20", "20-40", "40-60", "60-80", "80-a0", "a0-c0", "c0-e0", "e0-"} + count := 1 + for _, shard := range shards { + sbc := hc.AddTestTablet(cell, shard, 1, "TestExecutor", shard, topodatapb.TabletType_MASTER, true, 1, nil) + sbc.SetResults([]*sqltypes.Result{ + sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col", "int32|int32"), fmt.Sprintf("%d|%d", count, count)), + sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col", "int32|int32"), fmt.Sprintf("%d|%d", count+10, count)), + }) + count++ + } + executor := NewExecutor(context.Background(), serv, cell, resolver, false, testBufferSize, testCacheSize) + before := runtime.NumGoroutine() + + query := "select id, col from user order by id limit 2" + gotResult, err := executorStream(executor, query) + require.NoError(t, err) + + wantResult := sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|col", "int32|int32"), "1|1", "2|2") + wantResult.RowsAffected = 0 + utils.MustMatch(t, wantResult, gotResult) + // some sleep to close all goroutines. + time.Sleep(100 * time.Millisecond) + assert.GreaterOrEqual(t, before, runtime.NumGoroutine(), "left open goroutines lingering") +} diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 823cb312de1..89bb04eaf1f 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -198,10 +198,24 @@ func (sbc *SandboxConn) StreamExecute(ctx context.Context, target *querypb.Targe sbc.sExecMu.Unlock() return err } - nextRs := sbc.getNextResult() + if sbc.results == nil { + nextRs := sbc.getNextResult() + sbc.sExecMu.Unlock() + return callback(nextRs) + } + + for len(sbc.results) > 0 { + nextRs := sbc.getNextResult() + sbc.sExecMu.Unlock() + err := callback(nextRs) + if err != nil { + return err + } + sbc.sExecMu.Lock() + } sbc.sExecMu.Unlock() - return callback(nextRs) + return nil } // Begin is part of the QueryService interface. From cde403a65dfae01da6d1211744c4314ad81857f4 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 22 Apr 2021 23:20:21 +0530 Subject: [PATCH 22/49] squashed backport of PR 7879 Signed-off-by: Harshit Gangal --- .../endtoend/vtgate/reservedconn/main_test.go | 6 +- .../reservedconn/reconnect1/main_test.go | 150 ++++++++++++++++++ .../reservedconn/reconnect2/main_test.go | 134 ++++++++++++++++ go/vt/discovery/fake_healthcheck.go | 19 ++- go/vt/discovery/healthcheck.go | 21 ++- go/vt/srvtopo/resilient_server_test.go | 6 +- go/vt/srvtopo/resolver.go | 2 +- go/vt/vterrors/constants.go | 34 ++++ go/vt/vtgate/discoverygateway.go | 2 +- go/vt/vtgate/gateway.go | 4 +- go/vt/vtgate/safe_session.go | 2 +- go/vt/vtgate/scatter_conn.go | 147 ++++++++++------- go/vt/vtgate/scatter_conn_test.go | 64 ++++++++ go/vt/vtgate/tabletgateway.go | 4 +- go/vt/vtgate/tx_conn.go | 2 +- go/vt/vttablet/sandboxconn/sandboxconn.go | 2 +- .../tabletconntest/fakequeryservice.go | 2 +- go/vt/vttablet/tabletserver/state_manager.go | 33 ++-- .../tabletserver/state_manager_test.go | 4 +- test/config.json | 18 +++ 20 files changed, 541 insertions(+), 115 deletions(-) create mode 100644 go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go create mode 100644 go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go create mode 100644 go/vt/vterrors/constants.go diff --git a/go/test/endtoend/vtgate/reservedconn/main_test.go b/go/test/endtoend/vtgate/reservedconn/main_test.go index 90d71e71753..9bac75fd1e3 100644 --- a/go/test/endtoend/vtgate/reservedconn/main_test.go +++ b/go/test/endtoend/vtgate/reservedconn/main_test.go @@ -126,10 +126,8 @@ func TestMain(m *testing.M) { } // Start vtgate - clusterInstance.VtGateExtraArgs = []string{"-lock_heartbeat_time", "2s"} - vtgateProcess := clusterInstance.NewVtgateInstance() - vtgateProcess.SysVarSetEnabled = true - if err := vtgateProcess.Setup(); err != nil { + clusterInstance.VtGateExtraArgs = []string{"-lock_heartbeat_time", "2s", "-enable_system_settings=true"} // enable reserved connection. + if err := clusterInstance.StartVtgate(); err != nil { return 1 } diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go new file mode 100644 index 00000000000..598d23345fe --- /dev/null +++ b/go/test/endtoend/vtgate/reservedconn/reconnect1/main_test.go @@ -0,0 +1,150 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package reservedconn + +import ( + "context" + "flag" + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + keyspaceName = "ks" + cell = "zone1" + hostname = "localhost" + sqlSchema = `create table test(id bigint primary key)Engine=InnoDB;` + + vSchema = ` + { + "sharded":true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "test":{ + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + } + ` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { + return 1 + } + + // Start vtgate + clusterInstance.VtGateExtraArgs = []string{"-lock_heartbeat_time", "2s", "-enable_system_settings=true"} // enable reserved connection. + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) +} + +func TestServingChange(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + checkedExec(t, conn, "use @rdonly") + checkedExec(t, conn, "set sql_mode = ''") + + // to see rdonly is available and + // also this will create reserved connection on rdonly on -80 and 80- shards. + _, err = exec(t, conn, "select * from test") + for err != nil { + _, err = exec(t, conn, "select * from test") + } + + // changing rdonly tablet to spare (non serving). + rdonlyTablet := clusterInstance.Keyspaces[0].Shards[0].Rdonly() + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", rdonlyTablet.Alias, "spare") + require.NoError(t, err) + + // this should fail as there is no rdonly present + _, err = exec(t, conn, "select * from test") + require.Error(t, err) + + // changing replica tablet to rdonly to make rdonly available for serving. + replicaTablet := clusterInstance.Keyspaces[0].Shards[0].Replica() + err = clusterInstance.VtctlclientProcess.ExecuteCommand("ChangeTabletType", replicaTablet.Alias, "rdonly") + require.NoError(t, err) + + // to see/make the new rdonly available + err = clusterInstance.VtctlclientProcess.ExecuteCommand("Ping", replicaTablet.Alias) + require.NoError(t, err) + + // this should pass now as there is rdonly present + _, err = exec(t, conn, "select * from test") + assert.NoError(t, err) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) (*sqltypes.Result, error) { + t.Helper() + return conn.ExecuteFetch(query, 1000, true) +} + +func checkedExec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.NoError(t, err) + return qr +} diff --git a/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go b/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go new file mode 100644 index 00000000000..627f203647e --- /dev/null +++ b/go/test/endtoend/vtgate/reservedconn/reconnect2/main_test.go @@ -0,0 +1,134 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package reservedconn + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + keyspaceName = "ks" + cell = "zone1" + hostname = "localhost" + sqlSchema = `create table test(id bigint primary key)Engine=InnoDB;` + + vSchema = ` + { + "sharded":true, + "vindexes": { + "hash_index": { + "type": "hash" + } + }, + "tables": { + "test":{ + "column_vindexes": [ + { + "column": "id", + "name": "hash_index" + } + ] + } + } + } + ` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: keyspaceName, + SchemaSQL: sqlSchema, + VSchema: vSchema, + } + clusterInstance.VtTabletExtraArgs = []string{"-queryserver-config-transaction-timeout", "5"} + if err := clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true); err != nil { + return 1 + } + + // Start vtgate + clusterInstance.VtGateExtraArgs = []string{"-lock_heartbeat_time", "2s", "-enable_system_settings=true"} // enable reserved connection. + if err := clusterInstance.StartVtgate(); err != nil { + return 1 + } + + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) +} + +func TestTabletChange(t *testing.T) { + conn, err := mysql.Connect(context.Background(), &vtParams) + require.NoError(t, err) + defer conn.Close() + + checkedExec(t, conn, "use @master") + checkedExec(t, conn, "set sql_mode = ''") + + // this will create reserved connection on master on -80 and 80- shards. + checkedExec(t, conn, "select * from test") + + // Change Master + err = clusterInstance.VtctlclientProcess.ExecuteCommand("PlannedReparentShard", "-keyspace_shard", fmt.Sprintf("%s/%s", keyspaceName, "-80")) + require.NoError(t, err) + + // this should pass as there is new master tablet and is serving. + _, err = exec(t, conn, "select * from test") + assert.NoError(t, err) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) (*sqltypes.Result, error) { + t.Helper() + return conn.ExecuteFetch(query, 1000, true) +} + +func checkedExec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.NoError(t, err) + return qr +} diff --git a/go/vt/discovery/fake_healthcheck.go b/go/vt/discovery/fake_healthcheck.go index c762eb48bec..bbb1ec98baa 100644 --- a/go/vt/discovery/fake_healthcheck.go +++ b/go/vt/discovery/fake_healthcheck.go @@ -21,20 +21,18 @@ import ( "sort" "sync" - "vitess.io/vitess/go/sync2" - "github.com/golang/protobuf/proto" - "vitess.io/vitess/go/vt/proto/vtrpc" - "vitess.io/vitess/go/vt/vterrors" - + "vitess.io/vitess/go/sync2" "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vttablet/queryservice" "vitess.io/vitess/go/vt/vttablet/sandboxconn" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) var ( @@ -146,16 +144,23 @@ func (fhc *FakeHealthCheck) ReplaceTablet(old, new *topodatapb.Tablet) { } // TabletConnection returns the TabletConn of the given tablet. -func (fhc *FakeHealthCheck) TabletConnection(alias *topodatapb.TabletAlias) (queryservice.QueryService, error) { +func (fhc *FakeHealthCheck) TabletConnection(alias *topodatapb.TabletAlias, target *querypb.Target) (queryservice.QueryService, error) { aliasStr := topoproto.TabletAliasString(alias) fhc.mu.RLock() defer fhc.mu.RUnlock() for _, item := range fhc.items { if proto.Equal(alias, item.ts.Tablet.Alias) { + if !item.ts.Serving { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.NotServing) + } + if target != nil && !proto.Equal(item.ts.Target, target) { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s: target mismatch %v vs %v", vterrors.WrongTablet, item.ts.Target, target) + } + return item.ts.Conn, nil } } - return nil, vterrors.Errorf(vtrpc.Code_NOT_FOUND, "tablet %v not found", aliasStr) + return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "tablet %v not found", aliasStr) } // CacheStatus returns the status for each tablet diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 4af9dfd7202..90a64a788aa 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -45,19 +45,18 @@ import ( "sync" "time" - "vitess.io/vitess/go/vt/proto/vtrpc" - "vitess.io/vitess/go/vt/vterrors" - "vitess.io/vitess/go/vt/vttablet/queryservice" + "github.com/golang/protobuf/proto" "vitess.io/vitess/go/flagutil" - - "vitess.io/vitess/go/vt/topo" - "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/log" "vitess.io/vitess/go/vt/proto/query" "vitess.io/vitess/go/vt/proto/topodata" + "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/topo" "vitess.io/vitess/go/vt/topo/topoproto" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/vt/vttablet/queryservice" ) var ( @@ -177,7 +176,7 @@ type HealthCheck interface { WaitForAllServingTablets(ctx context.Context, targets []*query.Target) error // TabletConnection returns the TabletConn of the given tablet. - TabletConnection(alias *topodata.TabletAlias) (queryservice.QueryService, error) + TabletConnection(alias *topodata.TabletAlias, target *query.Target) (queryservice.QueryService, error) // RegisterStats registers the connection counts stats RegisterStats() @@ -693,7 +692,7 @@ func (hc *HealthCheckImpl) waitForTablets(ctx context.Context, targets []*query. } // TabletConnection returns the Connection to a given tablet. -func (hc *HealthCheckImpl) TabletConnection(alias *topodata.TabletAlias) (queryservice.QueryService, error) { +func (hc *HealthCheckImpl) TabletConnection(alias *topodata.TabletAlias, target *query.Target) (queryservice.QueryService, error) { hc.mu.Lock() thc := hc.healthByAlias[tabletAliasString(topoproto.TabletAliasString(alias))] hc.mu.Unlock() @@ -701,6 +700,12 @@ func (hc *HealthCheckImpl) TabletConnection(alias *topodata.TabletAlias) (querys //TODO: test that throws this error return nil, vterrors.Errorf(vtrpc.Code_NOT_FOUND, "tablet: %v is either down or nonexistent", alias) } + if !thc.Serving { + return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, vterrors.NotServing) + } + if target != nil && !proto.Equal(thc.Target, target) { + return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "%s: target mismatch %v vs %v", vterrors.WrongTablet, thc.Target, target) + } return thc.Connection(), nil } diff --git a/go/vt/srvtopo/resilient_server_test.go b/go/vt/srvtopo/resilient_server_test.go index 40e50c200db..76f6d18dcbe 100644 --- a/go/vt/srvtopo/resilient_server_test.go +++ b/go/vt/srvtopo/resilient_server_test.go @@ -310,7 +310,8 @@ func TestGetSrvKeyspace(t *testing.T) { time.Sleep(*srvTopoCacheTTL) - timeoutCtx, _ := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint + timeoutCtx, cancel := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint + defer cancel() _, err = rs.GetSrvKeyspace(timeoutCtx, "test_cell", "test_ks") wantErr := "timed out waiting for keyspace" if err == nil || err.Error() != wantErr { @@ -614,7 +615,8 @@ func TestGetSrvKeyspaceNames(t *testing.T) { time.Sleep(*srvTopoCacheTTL) - timeoutCtx, _ := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint + timeoutCtx, cancel := context.WithTimeout(context.Background(), *srvTopoCacheRefresh*2) //nolint + defer cancel() _, err = rs.GetSrvKeyspaceNames(timeoutCtx, "test_cell", false) wantErr := "timed out waiting for keyspace names" if err == nil || err.Error() != wantErr { diff --git a/go/vt/srvtopo/resolver.go b/go/vt/srvtopo/resolver.go index 7134b0b9852..e668e0e248c 100644 --- a/go/vt/srvtopo/resolver.go +++ b/go/vt/srvtopo/resolver.go @@ -40,7 +40,7 @@ type Gateway interface { queryservice.QueryService // QueryServiceByAlias returns a QueryService - QueryServiceByAlias(alias *topodatapb.TabletAlias) (queryservice.QueryService, error) + QueryServiceByAlias(alias *topodatapb.TabletAlias, target *querypb.Target) (queryservice.QueryService, error) } // A Resolver can resolve keyspace ids and key ranges into ResolvedShard* diff --git a/go/vt/vterrors/constants.go b/go/vt/vterrors/constants.go new file mode 100644 index 00000000000..d66a97464d7 --- /dev/null +++ b/go/vt/vterrors/constants.go @@ -0,0 +1,34 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vterrors + +import "regexp" + +// Operation not allowed error +const ( + NotServing = "operation not allowed in state NOT_SERVING" + ShuttingDown = "operation not allowed in state SHUTTING_DOWN" +) + +// RxOp regex for operation not allowed error +var RxOp = regexp.MustCompile("operation not allowed in state (NOT_SERVING|SHUTTING_DOWN)") + +// WrongTablet for invalid tablet type error +const WrongTablet = "wrong tablet type" + +// RxWrongTablet regex for invalid tablet type error +var RxWrongTablet = regexp.MustCompile("(wrong|invalid) tablet type") diff --git a/go/vt/vtgate/discoverygateway.go b/go/vt/vtgate/discoverygateway.go index 6eac1575fa7..1d9b4dcc363 100644 --- a/go/vt/vtgate/discoverygateway.go +++ b/go/vt/vtgate/discoverygateway.go @@ -407,6 +407,6 @@ func (dg *DiscoveryGateway) getStatsAggregator(target *querypb.Target) *TabletSt } // QueryServiceByAlias satisfies the Gateway interface -func (dg *DiscoveryGateway) QueryServiceByAlias(_ *topodatapb.TabletAlias) (queryservice.QueryService, error) { +func (dg *DiscoveryGateway) QueryServiceByAlias(_ *topodatapb.TabletAlias, _ *querypb.Target) (queryservice.QueryService, error) { return nil, vterrors.New(vtrpcpb.Code_UNIMPLEMENTED, "DiscoveryGateway does not implement QueryServiceByAlias") } diff --git a/go/vt/vtgate/gateway.go b/go/vt/vtgate/gateway.go index 1398ad5419e..86a015ab77a 100644 --- a/go/vt/vtgate/gateway.go +++ b/go/vt/vtgate/gateway.go @@ -17,6 +17,8 @@ import ( "flag" "time" + querypb "vitess.io/vitess/go/vt/proto/query" + "context" "vitess.io/vitess/go/vt/log" @@ -68,7 +70,7 @@ type Gateway interface { TabletsCacheStatus() discovery.TabletsCacheStatusList // TabletByAlias returns a QueryService - QueryServiceByAlias(alias *topodatapb.TabletAlias) (queryservice.QueryService, error) + QueryServiceByAlias(alias *topodatapb.TabletAlias, target *querypb.Target) (queryservice.QueryService, error) } // Creator is the factory method which can create the actual gateway object. diff --git a/go/vt/vtgate/safe_session.go b/go/vt/vtgate/safe_session.go index ead6619b4af..5a83abe1fce 100644 --- a/go/vt/vtgate/safe_session.go +++ b/go/vt/vtgate/safe_session.go @@ -519,7 +519,7 @@ func removeShard(tabletAlias *topodatapb.TabletAlias, sessions []*vtgatepb.Sessi } } if idx == -1 { - return sessions, nil + return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "[BUG] tried to remove missing shard") } return append(sessions[:idx], sessions[idx+1:]...), nil } diff --git a/go/vt/vtgate/scatter_conn.go b/go/vt/vtgate/scatter_conn.go index e63f5499f80..e8d1da842e5 100644 --- a/go/vt/vtgate/scatter_conn.go +++ b/go/vt/vtgate/scatter_conn.go @@ -145,6 +145,14 @@ func (stc *ScatterConn) endAction(startTime time.Time, allErrors *concurrency.Al stc.timings.Record(statsKey, startTime) } +type reset int + +const ( + none reset = iota + shard + newQS +) + // ExecuteMultiShard is like Execute, // but each shard gets its own Sql Queries and BindVariables. // @@ -206,60 +214,82 @@ func (stc *ScatterConn) ExecuteMultiShard( if autocommit { // As this is auto-commit, the transactionID is supposed to be zero. - if info.transactionID != int64(0) { - return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "in autocommit mode, transactionID should be zero but was: %d", info.transactionID) + if transactionID != int64(0) { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "in autocommit mode, transactionID should be zero but was: %d", transactionID) } } qs, err = getQueryService(rs, info) if err != nil { - return nil, err + // an error here could mean that the tablet we were targeting earlier has changed type. + // if we have a transaction, we'll have to fail, but if we only had a reserved connection, + // we can create a new reserved connection to a new tablet that is on the right shard + // and has the right type + switch info.actionNeeded { + case nothing: + info.actionNeeded = reserve + case begin: + info.actionNeeded = reserveBegin + default: + return nil, err + } + retry := checkAndResetShardSession(info, err, session) + if retry != newQS { + return nil, err + } + qs = rs.Gateway + } + + retryRequest := func(exec func()) { + retry := checkAndResetShardSession(info, err, session) + switch retry { + case newQS: + // Current tablet is not available, try querying new tablet using gateway. + qs = rs.Gateway + fallthrough + case shard: + // if we need to reset a reserved connection, here is our chance to try executing again, + // against a new connection + exec() + } } switch info.actionNeeded { case nothing: innerqr, err = qs.Execute(ctx, rs.Target, queries[i].Sql, queries[i].BindVariables, info.transactionID, info.reservedID, opts) if err != nil { - shouldRetry := checkAndResetShardSession(info, err, session) - if shouldRetry { - // we seem to have lost our connection. if it was a reserved connection, let's try to recreate it + retryRequest(func() { + // we seem to have lost our connection. it was a reserved connection, let's try to recreate it info.actionNeeded = reserve innerqr, reservedID, alias, err = qs.ReserveExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, 0 /*transactionId*/, opts) - } - if err != nil { - return info.updateReservedID(reservedID, alias), err - } + }) } case begin: - innerqr, transactionID, alias, err = qs.BeginExecute(ctx, rs.Target, session.Savepoints, queries[i].Sql, queries[i].BindVariables, info.reservedID, opts) + innerqr, transactionID, alias, err = qs.BeginExecute(ctx, rs.Target, session.Savepoints, queries[i].Sql, queries[i].BindVariables, reservedID, opts) if err != nil { if transactionID != 0 { - return info.updateTransactionID(transactionID, alias), err + // if we had an open transaction, we can't repair anything and have to exit here. + // we still keep the transaction open - an error doesn't immediately close the transaction + break } - shouldRetry := checkAndResetShardSession(info, err, session) - if shouldRetry { - // we seem to have lost our connection. if it was a reserved connection, let's try to recreate it + retryRequest(func() { + // we seem to have lost our connection. it was a reserved connection, let's try to recreate it info.actionNeeded = reserveBegin innerqr, transactionID, reservedID, alias, err = qs.ReserveBeginExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, opts) - } - if err != nil { - return info.updateTransactionAndReservedID(transactionID, reservedID, alias), err - } - + }) } case reserve: - innerqr, reservedID, alias, err = qs.ReserveExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, info.transactionID, opts) - if err != nil { - return info.updateReservedID(reservedID, alias), err - } + innerqr, reservedID, alias, err = qs.ReserveExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, transactionID, opts) case reserveBegin: innerqr, transactionID, reservedID, alias, err = qs.ReserveBeginExecute(ctx, rs.Target, session.SetPreQueries(), queries[i].Sql, queries[i].BindVariables, opts) - if err != nil { - return info.updateTransactionAndReservedID(transactionID, reservedID, alias), err - } default: return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "BUG: unexpected actionNeeded on ScatterConn#ExecuteMultiShard %v", info.actionNeeded) } + // We need to new shard info irrespective of the error. + newInfo := info.updateTransactionAndReservedID(transactionID, reservedID, alias) + if err != nil { + return newInfo, err + } mu.Lock() defer mu.Unlock() @@ -267,7 +297,7 @@ func (stc *ScatterConn) ExecuteMultiShard( if ignoreMaxMemoryRows || len(qr.Rows) <= *maxMemoryRows { qr.AppendResult(innerqr) } - return info.updateTransactionAndReservedID(transactionID, reservedID, alias), nil + return newInfo, nil }, ) @@ -278,28 +308,32 @@ func (stc *ScatterConn) ExecuteMultiShard( return qr, allErrors.GetErrors() } -var errRegx = regexp.MustCompile("transaction ([a-z0-9:]+) (?:ended|not found)") - -func checkAndResetShardSession(info *shardActionInfo, err error, session *SafeSession) bool { - if info.reservedID != 0 && info.transactionID == 0 && wasConnectionClosed(err) { - session.ResetShard(info.alias) - return true +func checkAndResetShardSession(info *shardActionInfo, err error, session *SafeSession) reset { + retry := none + if info.reservedID != 0 && info.transactionID == 0 { + if wasConnectionClosed(err) { + retry = shard + } + if requireNewQS(err) { + retry = newQS + } } - return false + if retry != none { + _ = session.ResetShard(info.alias) + } + return retry } func getQueryService(rs *srvtopo.ResolvedShard, info *shardActionInfo) (queryservice.QueryService, error) { _, usingLegacyGw := rs.Gateway.(*DiscoveryGateway) - if usingLegacyGw { - switch info.actionNeeded { - case reserve, reserveBegin: - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "reserved connections are not supported on old gen gateway") - } + if usingLegacyGw && + (info.actionNeeded == reserve || info.actionNeeded == reserveBegin) { + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "reserved connections are not supported on old gen gateway") } if usingLegacyGw || info.alias == nil { return rs.Gateway, nil } - return rs.Gateway.QueryServiceByAlias(info.alias) + return rs.Gateway.QueryServiceByAlias(info.alias, rs.Target) } func (stc *ScatterConn) processOneStreamingResult(mu *sync.Mutex, fieldSent *bool, qr *sqltypes.Result, callback func(*sqltypes.Result) error) error { @@ -675,12 +709,21 @@ func (stc *ScatterConn) ExecuteLock( return qr, err } +var txClosed = regexp.MustCompile("transaction ([a-z0-9:]+) (?:ended|not found)") + func wasConnectionClosed(err error) bool { sqlErr := mysql.NewSQLErrorFromError(err).(*mysql.SQLError) + message := sqlErr.Error() return sqlErr.Number() == mysql.CRServerGone || sqlErr.Number() == mysql.CRServerLost || - (sqlErr.Number() == mysql.ERQueryInterrupted && errRegx.MatchString(sqlErr.Error())) + (sqlErr.Number() == mysql.ERQueryInterrupted && txClosed.MatchString(message)) +} + +func requireNewQS(err error) bool { + code := vterrors.Code(err) + msg := err.Error() + return code == vtrpcpb.Code_FAILED_PRECONDITION && (vterrors.RxOp.MatchString(msg) || vterrors.RxWrongTablet.MatchString(msg)) } // actionInfo looks at the current session, and returns information about what needs to be done for this tablet @@ -738,25 +781,9 @@ type shardActionInfo struct { alias *topodatapb.TabletAlias } -func (sai *shardActionInfo) updateTransactionID(txID int64, alias *topodatapb.TabletAlias) *shardActionInfo { - if txID == 0 { - // As transaction id is ZERO, there is nothing to update in session shard sessions. - return nil - } - return sai.updateTransactionAndReservedID(txID, sai.reservedID, alias) -} - -func (sai *shardActionInfo) updateReservedID(rID int64, alias *topodatapb.TabletAlias) *shardActionInfo { - if rID == 0 { - // As reserved id is ZERO, there is nothing to update in session shard sessions. - return nil - } - return sai.updateTransactionAndReservedID(sai.transactionID, rID, alias) -} - func (sai *shardActionInfo) updateTransactionAndReservedID(txID int64, rID int64, alias *topodatapb.TabletAlias) *shardActionInfo { - if txID == 0 && rID == 0 { - // As transaction id and reserved id is ZERO, there is nothing to update in session shard sessions. + if txID == sai.transactionID && rID == sai.reservedID { + // As transaction id and reserved id have not changed, there is nothing to update in session shard sessions. return nil } newInfo := *sai diff --git a/go/vt/vtgate/scatter_conn_test.go b/go/vt/vtgate/scatter_conn_test.go index 49b85b1123a..a0797f89f23 100644 --- a/go/vt/vtgate/scatter_conn_test.go +++ b/go/vt/vtgate/scatter_conn_test.go @@ -19,6 +19,8 @@ package vtgate import ( "testing" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "github.com/stretchr/testify/assert" "vitess.io/vitess/go/mysql" @@ -321,6 +323,68 @@ func TestReservedConnFail(t *testing.T) { assert.Equal(t, 2, len(sbc0.Queries), "one for the failed attempt, and one for the retry") require.Equal(t, 1, len(session.ShardSessions)) assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") + oldRId = session.Session.ShardSessions[0].ReservedId + + sbc0.Queries = nil + sbc0.EphemeralShardErr = vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "operation not allowed in state NOT_SERVING during query: query1") + _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) + assert.Equal(t, 2, len(sbc0.Queries), "one for the failed attempt, and one for the retry") + require.Equal(t, 1, len(session.ShardSessions)) + assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") + oldRId = session.Session.ShardSessions[0].ReservedId + + sbc0.Queries = nil + sbc0.EphemeralShardErr = vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "invalid tablet type: REPLICA, want: MASTER or MASTER") + _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) + assert.Equal(t, 2, len(sbc0.Queries), "one for the failed attempt, and one for the retry") + require.Equal(t, 1, len(session.ShardSessions)) + assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") + oldRId = session.Session.ShardSessions[0].ReservedId + oldAlias := session.Session.ShardSessions[0].TabletAlias + + // Test Setup + tablet0 := sbc0.Tablet() + ths := hc.GetHealthyTabletStats(&querypb.Target{ + Keyspace: tablet0.GetKeyspace(), + Shard: tablet0.GetShard(), + TabletType: tablet0.GetType(), + }) + sbc0Th := ths[0] + sbc0Th.Serving = false + sbc0Rep := hc.AddTestTablet("aa", "0", 2, keyspace, "0", topodatapb.TabletType_REPLICA, true, 1, nil) + + sbc0.Queries = nil + _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) + assert.Equal(t, 0, len(sbc0.Queries), "no attempt should be made as the tablet is not serving") + assert.Equal(t, 1, len(sbc0Rep.Queries), "first attempt should pass as it is healthy") + require.Equal(t, 1, len(session.ShardSessions)) + assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") + assert.NotEqual(t, oldAlias, session.Session.ShardSessions[0].TabletAlias, "tablet alias should have changed as this is a different tablet") + oldRId = session.Session.ShardSessions[0].ReservedId + oldAlias = session.Session.ShardSessions[0].TabletAlias + + // Test Setup + tablet0Rep := sbc0Rep.Tablet() + newThs := hc.GetHealthyTabletStats(&querypb.Target{ + Keyspace: tablet0Rep.GetKeyspace(), + Shard: tablet0Rep.GetShard(), + TabletType: tablet0Rep.GetType(), + }) + sbc0RepTh := newThs[0] + sbc0RepTh.Target = &querypb.Target{ + Keyspace: tablet0Rep.GetKeyspace(), + Shard: tablet0Rep.GetShard(), + TabletType: topodatapb.TabletType_SPARE, + } + sbc0Th.Serving = true + + sbc0Rep.Queries = nil + _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) + assert.Equal(t, 1, len(sbc0.Queries), "first attempt should pass as it is healthy and matches the target") + assert.Equal(t, 0, len(sbc0Rep.Queries), " no attempt should be made as the tablet target is changed") + require.Equal(t, 1, len(session.ShardSessions)) + assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") + assert.NotEqual(t, oldAlias, session.Session.ShardSessions[0].TabletAlias, "tablet alias should have changed as this is a different tablet") } func TestIsConnClosed(t *testing.T) { diff --git a/go/vt/vtgate/tabletgateway.go b/go/vt/vtgate/tabletgateway.go index b7ddf31db6b..6e70058d241 100644 --- a/go/vt/vtgate/tabletgateway.go +++ b/go/vt/vtgate/tabletgateway.go @@ -134,8 +134,8 @@ func NewTabletGateway(ctx context.Context, hc discovery.HealthCheck, serv srvtop } // QueryServiceByAlias satisfies the Gateway interface -func (gw *TabletGateway) QueryServiceByAlias(alias *topodatapb.TabletAlias) (queryservice.QueryService, error) { - return gw.hc.TabletConnection(alias) +func (gw *TabletGateway) QueryServiceByAlias(alias *topodatapb.TabletAlias, target *querypb.Target) (queryservice.QueryService, error) { + return gw.hc.TabletConnection(alias, target) } // RegisterStats registers the stats to export the lag since the last refresh diff --git a/go/vt/vtgate/tx_conn.go b/go/vt/vtgate/tx_conn.go index 4747dcf2664..b056b8db508 100644 --- a/go/vt/vtgate/tx_conn.go +++ b/go/vt/vtgate/tx_conn.go @@ -87,7 +87,7 @@ func (txc *TxConn) queryService(alias *topodatapb.TabletAlias) (queryservice.Que if qs != nil { return qs, nil } - return txc.gateway.QueryServiceByAlias(alias) + return txc.gateway.QueryServiceByAlias(alias, nil) } func (txc *TxConn) commitShard(ctx context.Context, s *vtgatepb.Session_ShardSession) error { diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 823cb312de1..a352cd3ce56 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -430,7 +430,7 @@ func (sbc *SandboxConn) VStreamResults(ctx context.Context, target *querypb.Targ } // QueryServiceByAlias is part of the Gateway interface. -func (sbc *SandboxConn) QueryServiceByAlias(_ *topodatapb.TabletAlias) (queryservice.QueryService, error) { +func (sbc *SandboxConn) QueryServiceByAlias(_ *topodatapb.TabletAlias, _ *querypb.Target) (queryservice.QueryService, error) { return sbc, nil } diff --git a/go/vt/vttablet/tabletconntest/fakequeryservice.go b/go/vt/vttablet/tabletconntest/fakequeryservice.go index 2ef76a239b2..ec5cc103efd 100644 --- a/go/vt/vttablet/tabletconntest/fakequeryservice.go +++ b/go/vt/vttablet/tabletconntest/fakequeryservice.go @@ -720,7 +720,7 @@ func (f *FakeQueryService) VStreamResults(ctx context.Context, target *querypb.T } // QueryServiceByAlias satisfies the Gateway interface -func (f *FakeQueryService) QueryServiceByAlias(_ *topodatapb.TabletAlias) (queryservice.QueryService, error) { +func (f *FakeQueryService) QueryServiceByAlias(_ *topodatapb.TabletAlias, _ *querypb.Target) (queryservice.QueryService, error) { panic("not implemented") } diff --git a/go/vt/vttablet/tabletserver/state_manager.go b/go/vt/vttablet/tabletserver/state_manager.go index 7aef0bbd083..2ba19135a1e 100644 --- a/go/vt/vttablet/tabletserver/state_manager.go +++ b/go/vt/vttablet/tabletserver/state_manager.go @@ -348,36 +348,19 @@ func (sm *stateManager) StartRequest(ctx context.Context, target *querypb.Target if sm.state != StateServing || !sm.replHealthy { // This specific error string needs to be returned for vtgate buffering to work. - return vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "operation not allowed in state NOT_SERVING") + return vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.NotServing) } shuttingDown := sm.wantState != StateServing if shuttingDown && !allowOnShutdown { // This specific error string needs to be returned for vtgate buffering to work. - return vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "operation not allowed in state SHUTTING_DOWN") + return vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.ShuttingDown) } - if target != nil { - switch { - case target.Keyspace != sm.target.Keyspace: - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid keyspace %v does not match expected %v", target.Keyspace, sm.target.Keyspace) - case target.Shard != sm.target.Shard: - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid shard %v does not match expected %v", target.Shard, sm.target.Shard) - case target.TabletType != sm.target.TabletType: - for _, otherType := range sm.alsoAllow { - if target.TabletType == otherType { - goto ok - } - } - return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "invalid tablet type: %v, want: %v or %v", target.TabletType, sm.target.TabletType, sm.alsoAllow) - } - } else { - if !tabletenv.IsLocalContext(ctx) { - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "No target") - } + err = sm.verifyTargetLocked(ctx, target) + if err != nil { + return err } - -ok: sm.requests.Add(1) return nil } @@ -392,6 +375,10 @@ func (sm *stateManager) EndRequest() { func (sm *stateManager) VerifyTarget(ctx context.Context, target *querypb.Target) error { sm.mu.Lock() defer sm.mu.Unlock() + return sm.verifyTargetLocked(ctx, target) +} + +func (sm *stateManager) verifyTargetLocked(ctx context.Context, target *querypb.Target) error { if target != nil { switch { case target.Keyspace != sm.target.Keyspace: @@ -404,7 +391,7 @@ func (sm *stateManager) VerifyTarget(ctx context.Context, target *querypb.Target return nil } } - return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "invalid tablet type: %v, want: %v or %v", target.TabletType, sm.target.TabletType, sm.alsoAllow) + return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s: %v, want: %v or %v", vterrors.WrongTablet, sm.target.TabletType, sm.target.TabletType, sm.alsoAllow) } } else { if !tabletenv.IsLocalContext(ctx) { diff --git a/go/vt/vttablet/tabletserver/state_manager_test.go b/go/vt/vttablet/tabletserver/state_manager_test.go index 4349212ffec..bc1ff4ca52e 100644 --- a/go/vt/vttablet/tabletserver/state_manager_test.go +++ b/go/vt/vttablet/tabletserver/state_manager_test.go @@ -531,9 +531,9 @@ func TestStateManagerValidations(t *testing.T) { target.Shard = "" target.TabletType = topodatapb.TabletType_REPLICA err = sm.StartRequest(ctx, target, false) - assert.Contains(t, err.Error(), "invalid tablet type") + assert.Contains(t, err.Error(), "wrong tablet type") err = sm.VerifyTarget(ctx, target) - assert.Contains(t, err.Error(), "invalid tablet type") + assert.Contains(t, err.Error(), "wrong tablet type") sm.alsoAllow = []topodatapb.TabletType{topodatapb.TabletType_REPLICA} err = sm.StartRequest(ctx, target, false) diff --git a/test/config.json b/test/config.json index 15b0fe79313..7e61da70002 100644 --- a/test/config.json +++ b/test/config.json @@ -515,6 +515,24 @@ "RetryMax": 0, "Tags": [] }, + "vtgate_reserved_conn1": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect1"], + "Command": [], + "Manual": false, + "Shard": "17", + "RetryMax": 0, + "Tags": [] + }, + "vtgate_reserved_conn2": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect2"], + "Command": [], + "Manual": false, + "Shard": "17", + "RetryMax": 0, + "Tags": [] + }, "vtgate_transaction": { "File": "unused.go", "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/transaction"], From 2266801a4dcb74b8626ec2b0a4b943a67cd94236 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 5 May 2021 11:39:29 +0530 Subject: [PATCH 23/49] fix test config Signed-off-by: Harshit Gangal --- test/config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/config.json b/test/config.json index 7e61da70002..db88399ce1d 100644 --- a/test/config.json +++ b/test/config.json @@ -520,7 +520,7 @@ "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect1"], "Command": [], "Manual": false, - "Shard": "17", + "Shard": 17, "RetryMax": 0, "Tags": [] }, @@ -529,7 +529,7 @@ "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/reservedconn/reconnect2"], "Command": [], "Manual": false, - "Shard": "17", + "Shard": 17, "RetryMax": 0, "Tags": [] }, From 684b9f0ea65027001c1ed41fea57c900afb45390 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 11 Feb 2021 18:13:15 +0530 Subject: [PATCH 24/49] added e2e test for query serving even when topo server is down Signed-off-by: Harshit Gangal --- .../endtoend/vtgate/unsharded/main_test.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index 4dc3fd70287..013dbe6b60b 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -181,6 +181,26 @@ func TestEmptyStatement(t *testing.T) { assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) } +func TestTopoDownServingQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + defer exec(t, conn, `delete from t1`) + + execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) + clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, "consul") + time.Sleep(3 * time.Second) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) +} + func TestInsertAllDefaults(t *testing.T) { defer cluster.PanicHandler(t) ctx := context.Background() From 017703ed44c855133beee35ce08aec2273cb22f9 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Thu, 11 Feb 2021 18:13:47 +0530 Subject: [PATCH 25/49] do not evict cache if unable to connect to topo server Signed-off-by: Harshit Gangal --- go/vt/srvtopo/resilient_server.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/go/vt/srvtopo/resilient_server.go b/go/vt/srvtopo/resilient_server.go index f47f3f9be11..97c2fd1c311 100644 --- a/go/vt/srvtopo/resilient_server.go +++ b/go/vt/srvtopo/resilient_server.go @@ -20,6 +20,7 @@ import ( "flag" "fmt" "html/template" + "net/url" "sort" "sync" "time" @@ -466,7 +467,9 @@ func (server *ResilientServer) watchSrvKeyspace(callerCtx context.Context, entry server.counts.Add(errorCategory, 1) log.Errorf("Initial WatchSrvKeyspace failed for %v/%v: %v", cell, keyspace, current.Err) - if time.Since(entry.lastValueTime) > server.cacheTTL { + // This watcher will able to continue to return the last value till it is not able to connect to the topo server even if the cache TTL is reached. + _, netErr := current.Err.(*url.Error) + if !netErr && time.Since(entry.lastValueTime) > server.cacheTTL { log.Errorf("WatchSrvKeyspace clearing cached entry for %v/%v", cell, keyspace) entry.value = nil } From bf018aa89cb6b19616afb4f82b37f0d809e0ada5 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Mon, 15 Feb 2021 07:06:21 +0100 Subject: [PATCH 26/49] make sure to keep data even when topo server is deleted Signed-off-by: Andres Taylor --- go/test/endtoend/cluster/topo_process.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/test/endtoend/cluster/topo_process.go b/go/test/endtoend/cluster/topo_process.go index c78d251768f..01c90906482 100644 --- a/go/test/endtoend/cluster/topo_process.go +++ b/go/test/endtoend/cluster/topo_process.go @@ -230,7 +230,7 @@ func (topo *TopoProcess) TearDown(Cell string, originalVtRoot string, currentRoo // Attempt graceful shutdown with SIGTERM first _ = topo.proc.Process.Signal(syscall.SIGTERM) - if !*keepData { + if !(*keepData || keepdata) { _ = os.RemoveAll(topo.DataDirectory) _ = os.RemoveAll(currentRoot) } From 25d02dd171039198dc19376c325626f36cadae26 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 15 Feb 2021 13:16:45 +0530 Subject: [PATCH 27/49] added toposerver down testing for zk, consul and etcd Signed-off-by: Harshit Gangal --- go/test/endtoend/cluster/cluster_process.go | 13 +- go/test/endtoend/topotest/consul/main_test.go | 148 ++++++++++++++++++ go/test/endtoend/topotest/etcd2/main_test.go | 147 +++++++++++++++++ go/test/endtoend/topotest/zk2/main_test.go | 148 ++++++++++++++++++ .../endtoend/vtgate/unsharded/main_test.go | 2 +- 5 files changed, 454 insertions(+), 4 deletions(-) create mode 100644 go/test/endtoend/topotest/consul/main_test.go create mode 100644 go/test/endtoend/topotest/etcd2/main_test.go create mode 100644 go/test/endtoend/topotest/zk2/main_test.go diff --git a/go/test/endtoend/cluster/cluster_process.go b/go/test/endtoend/cluster/cluster_process.go index 879b2ef8a0e..c92de019d90 100644 --- a/go/test/endtoend/cluster/cluster_process.go +++ b/go/test/endtoend/cluster/cluster_process.go @@ -56,6 +56,7 @@ type LocalProcessCluster struct { Cell string BaseTabletUID int Hostname string + TopoFlavor string TopoPort int TmpDirectory string OriginalVTDATAROOT string @@ -173,6 +174,8 @@ func (cluster *LocalProcessCluster) StartTopo() (err error) { if cluster.Cell == "" { cluster.Cell = DefaultCell } + + topoFlavor = cluster.TopoFlavorString() cluster.TopoPort = cluster.GetAndReservePort() cluster.TmpDirectory = path.Join(os.Getenv("VTDATAROOT"), fmt.Sprintf("/tmp_%d", cluster.GetAndReservePort())) cluster.TopoProcess = *TopoProcessInstance(cluster.TopoPort, cluster.GetAndReservePort(), cluster.Hostname, *topoFlavor, "global") @@ -758,9 +761,13 @@ func (cluster *LocalProcessCluster) StartVttablet(tablet *Vttablet, servingStatu return tablet.VttabletProcess.Setup() } -//func (cluster *LocalProcessCluster) NewOrcInstance() OrchestratorProcess { -// -//} +// TopoFlavorString returns the topo flavor +func (cluster *LocalProcessCluster) TopoFlavorString() *string { + if cluster.TopoFlavor != "" { + return &cluster.TopoFlavor + } + return topoFlavor +} func getCoveragePath(fileName string) string { covDir := os.Getenv("COV_DIR") diff --git a/go/test/endtoend/topotest/consul/main_test.go b/go/test/endtoend/topotest/consul/main_test.go new file mode 100644 index 00000000000..f805c7c00b0 --- /dev/null +++ b/go/test/endtoend/topotest/consul/main_test.go @@ -0,0 +1,148 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package consul + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + "time" + + "vitess.io/vitess/go/vt/log" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + cell = "zone1" + hostname = "localhost" + KeyspaceName = "customer" + SchemaSQL = ` +CREATE TABLE t1 ( + c1 BIGINT NOT NULL, + c2 BIGINT NOT NULL, + c3 BIGINT, + c4 varchar(100), + PRIMARY KEY (c1), + UNIQUE KEY (c2), + UNIQUE KEY (c3), + UNIQUE KEY (c4) +) ENGINE=Innodb;` + VSchema = ` +{ + "sharded": false, + "tables": { + "t1": {} + } +} +` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + clusterInstance.TopoFlavor = "consul" + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + Keyspace := &cluster.Keyspace{ + Name: KeyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { + log.Fatal(err.Error()) + return 1 + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + log.Fatal(err.Error()) + return 1 + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestTopoDownServingQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + defer exec(t, conn, `delete from t1`) + + execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) + clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString()) + time.Sleep(3 * time.Second) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.NoError(t, err) + return qr +} + +func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result { + t.Helper() + var res []*sqltypes.Result + qr, more, err := conn.ExecuteFetchMulti(query, 1000, true) + res = append(res, qr) + require.NoError(t, err) + for more == true { + qr, more, _, err = conn.ReadQueryResult(1000, true) + require.NoError(t, err) + res = append(res, qr) + } + return res +} + +func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { + t.Helper() + qr := exec(t, conn, query) + got := fmt.Sprintf("%v", qr.Rows) + diff := cmp.Diff(expected, got) + if diff != "" { + t.Errorf("Query: %s (-want +got):\n%s", query, diff) + } +} diff --git a/go/test/endtoend/topotest/etcd2/main_test.go b/go/test/endtoend/topotest/etcd2/main_test.go new file mode 100644 index 00000000000..67ffb32ee6e --- /dev/null +++ b/go/test/endtoend/topotest/etcd2/main_test.go @@ -0,0 +1,147 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ectd2 + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + "time" + + "vitess.io/vitess/go/vt/log" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + cell = "zone1" + hostname = "localhost" + KeyspaceName = "customer" + SchemaSQL = ` +CREATE TABLE t1 ( + c1 BIGINT NOT NULL, + c2 BIGINT NOT NULL, + c3 BIGINT, + c4 varchar(100), + PRIMARY KEY (c1), + UNIQUE KEY (c2), + UNIQUE KEY (c3), + UNIQUE KEY (c4) +) ENGINE=Innodb;` + VSchema = ` +{ + "sharded": false, + "tables": { + "t1": {} + } +} +` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + Keyspace := &cluster.Keyspace{ + Name: KeyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { + log.Fatal(err.Error()) + return 1 + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + log.Fatal(err.Error()) + return 1 + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestTopoDownServingQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + defer exec(t, conn, `delete from t1`) + + execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) + clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString()) + time.Sleep(3 * time.Second) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.NoError(t, err) + return qr +} + +func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result { + t.Helper() + var res []*sqltypes.Result + qr, more, err := conn.ExecuteFetchMulti(query, 1000, true) + res = append(res, qr) + require.NoError(t, err) + for more == true { + qr, more, _, err = conn.ReadQueryResult(1000, true) + require.NoError(t, err) + res = append(res, qr) + } + return res +} + +func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { + t.Helper() + qr := exec(t, conn, query) + got := fmt.Sprintf("%v", qr.Rows) + diff := cmp.Diff(expected, got) + if diff != "" { + t.Errorf("Query: %s (-want +got):\n%s", query, diff) + } +} diff --git a/go/test/endtoend/topotest/zk2/main_test.go b/go/test/endtoend/topotest/zk2/main_test.go new file mode 100644 index 00000000000..611bee7d180 --- /dev/null +++ b/go/test/endtoend/topotest/zk2/main_test.go @@ -0,0 +1,148 @@ +/* +Copyright 2021 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package zk2 + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + "time" + + "vitess.io/vitess/go/vt/log" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + cell = "zone1" + hostname = "localhost" + KeyspaceName = "customer" + SchemaSQL = ` +CREATE TABLE t1 ( + c1 BIGINT NOT NULL, + c2 BIGINT NOT NULL, + c3 BIGINT, + c4 varchar(100), + PRIMARY KEY (c1), + UNIQUE KEY (c2), + UNIQUE KEY (c3), + UNIQUE KEY (c4) +) ENGINE=Innodb;` + VSchema = ` +{ + "sharded": false, + "tables": { + "t1": {} + } +} +` +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(cell, hostname) + defer clusterInstance.Teardown() + + // Start topo server + clusterInstance.TopoFlavor = "zk2" + if err := clusterInstance.StartTopo(); err != nil { + return 1 + } + + // Start keyspace + Keyspace := &cluster.Keyspace{ + Name: KeyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + } + if err := clusterInstance.StartUnshardedKeyspace(*Keyspace, 0, false); err != nil { + log.Fatal(err.Error()) + return 1 + } + + // Start vtgate + if err := clusterInstance.StartVtgate(); err != nil { + log.Fatal(err.Error()) + return 1 + } + + return m.Run() + }() + os.Exit(exitCode) +} + +func TestTopoDownServingQuery(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + vtParams := mysql.ConnParams{ + Host: "localhost", + Port: clusterInstance.VtgateMySQLPort, + } + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + defer conn.Close() + + defer exec(t, conn, `delete from t1`) + + execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) + clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString()) + time.Sleep(3 * time.Second) + assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) +} + +func exec(t *testing.T, conn *mysql.Conn, query string) *sqltypes.Result { + t.Helper() + qr, err := conn.ExecuteFetch(query, 1000, true) + require.NoError(t, err) + return qr +} + +func execMulti(t *testing.T, conn *mysql.Conn, query string) []*sqltypes.Result { + t.Helper() + var res []*sqltypes.Result + qr, more, err := conn.ExecuteFetchMulti(query, 1000, true) + res = append(res, qr) + require.NoError(t, err) + for more == true { + qr, more, _, err = conn.ReadQueryResult(1000, true) + require.NoError(t, err) + res = append(res, qr) + } + return res +} + +func assertMatches(t *testing.T, conn *mysql.Conn, query, expected string) { + t.Helper() + qr := exec(t, conn, query) + got := fmt.Sprintf("%v", qr.Rows) + diff := cmp.Diff(expected, got) + if diff != "" { + t.Errorf("Query: %s (-want +got):\n%s", query, diff) + } +} diff --git a/go/test/endtoend/vtgate/unsharded/main_test.go b/go/test/endtoend/vtgate/unsharded/main_test.go index 013dbe6b60b..09089e00e05 100644 --- a/go/test/endtoend/vtgate/unsharded/main_test.go +++ b/go/test/endtoend/vtgate/unsharded/main_test.go @@ -196,7 +196,7 @@ func TestTopoDownServingQuery(t *testing.T) { execMulti(t, conn, `insert into t1(c1, c2, c3, c4) values (300,100,300,'abc'); ;; insert into t1(c1, c2, c3, c4) values (301,101,301,'abcd');;`) assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) - clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, "consul") + clusterInstance.TopoProcess.TearDown(clusterInstance.Cell, clusterInstance.OriginalVTDATAROOT, clusterInstance.CurrentVTDATAROOT, true, *clusterInstance.TopoFlavorString()) time.Sleep(3 * time.Second) assertMatches(t, conn, `select c1,c2,c3 from t1`, `[[INT64(300) INT64(100) INT64(300)] [INT64(301) INT64(101) INT64(301)]]`) } From bff68910aa17348ffd81c211a89f87814e30fcc1 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 15 Feb 2021 13:18:14 +0530 Subject: [PATCH 28/49] added to ci tests Signed-off-by: Harshit Gangal --- test/config.json | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/config.json b/test/config.json index db88399ce1d..8f84e89021e 100644 --- a/test/config.json +++ b/test/config.json @@ -569,6 +569,33 @@ "RetryMax": 0, "Tags": [] }, + "topo_zk2": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2"], + "Command": [], + "Manual": false, + "Shard": "17", + "RetryMax": 0, + "Tags": [] + }, + "topo_consul": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul"], + "Command": [], + "Manual": false, + "Shard": "17", + "RetryMax": 0, + "Tags": [] + }, + "topo_etcd2": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/etcd2"], + "Command": [], + "Manual": false, + "Shard": "17", + "RetryMax": 0, + "Tags": [] + }, "web_test": { "File": "unused.go", "Args": ["vitess.io/vitess/go/test/endtoend/vtctldweb"], From d32e22b2dfe7625439aef879b52db30e77abee43 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 15 Feb 2021 16:02:30 +0530 Subject: [PATCH 29/49] fixed e2e test config for zk and consul Signed-off-by: Harshit Gangal --- test.go | 2 +- test/config.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test.go b/test.go index bf355e39a72..1e324a97d92 100755 --- a/test.go +++ b/test.go @@ -69,7 +69,7 @@ To pass extra args to Python tests (test/*.py), terminate the list of test names with -- and then add them at the end. For example: - go run test.go test1 test2 -- --topo-server-flavor=etcd2 + go run test.go test1 test2 -- --topo-flavor=etcd2 ` // Flags diff --git a/test/config.json b/test/config.json index 8f84e89021e..50757077a04 100644 --- a/test/config.json +++ b/test/config.json @@ -571,7 +571,7 @@ }, "topo_zk2": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2"], + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2", "-topo-flavor", "zk2"], "Command": [], "Manual": false, "Shard": "17", @@ -580,7 +580,7 @@ }, "topo_consul": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul"], + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul", "-topo-flavor", "consul"], "Command": [], "Manual": false, "Shard": "17", From f7ce46dbb4ca31cd53f8d33fd6e3b71ad595e88f Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 16 Feb 2021 19:24:53 +0530 Subject: [PATCH 30/49] test in right shard Signed-off-by: Harshit Gangal --- test/config.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/config.json b/test/config.json index 50757077a04..98ab90c34f4 100644 --- a/test/config.json +++ b/test/config.json @@ -571,19 +571,19 @@ }, "topo_zk2": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2", "-topo-flavor", "zk2"], + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2", "--topo-flavor=zk2"], "Command": [], "Manual": false, - "Shard": "17", + "Shard": "25", "RetryMax": 0, "Tags": [] }, "topo_consul": { "File": "unused.go", - "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul", "-topo-flavor", "consul"], + "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul", "--topo-flavor=consul"], "Command": [], "Manual": false, - "Shard": "17", + "Shard": "18", "RetryMax": 0, "Tags": [] }, From d088c608f14033d89a7ce71708ab68b68b6da96a Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 5 May 2021 18:27:41 +0530 Subject: [PATCH 31/49] fix test config Signed-off-by: Harshit Gangal --- test/config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/config.json b/test/config.json index 98ab90c34f4..95fba07112b 100644 --- a/test/config.json +++ b/test/config.json @@ -574,7 +574,7 @@ "Args": ["vitess.io/vitess/go/test/endtoend/topotest/zk2", "--topo-flavor=zk2"], "Command": [], "Manual": false, - "Shard": "25", + "Shard": 25, "RetryMax": 0, "Tags": [] }, @@ -583,7 +583,7 @@ "Args": ["vitess.io/vitess/go/test/endtoend/topotest/consul", "--topo-flavor=consul"], "Command": [], "Manual": false, - "Shard": "18", + "Shard": 18, "RetryMax": 0, "Tags": [] }, @@ -592,7 +592,7 @@ "Args": ["vitess.io/vitess/go/test/endtoend/topotest/etcd2"], "Command": [], "Manual": false, - "Shard": "17", + "Shard": 17, "RetryMax": 0, "Tags": [] }, From 3529118bf8efb03ec9ac3f6b892d39a4f9f4ba78 Mon Sep 17 00:00:00 2001 From: Rohit Nayak Date: Wed, 17 Feb 2021 10:51:24 +0100 Subject: [PATCH 32/49] Rebuild SrvVSchema after deleting routing rules on MoveTables completion/cancellation This is a combination of 4 commits. This is the commit message #2: Check that routing rules are deleted in unit test This is the commit message #3: Fix typo This is the commit message #4: Refresh all tablets in a shard when updating blacklisted tables Signed-off-by: Rohit Nayak Signed-off-by: Andres Taylor --- go/vt/wrangler/traffic_switcher.go | 13 ++++++++++--- go/vt/wrangler/traffic_switcher_test.go | 20 +++++++++++++++++++- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/go/vt/wrangler/traffic_switcher.go b/go/vt/wrangler/traffic_switcher.go index d380fd78835..6e2960a17bd 100644 --- a/go/vt/wrangler/traffic_switcher.go +++ b/go/vt/wrangler/traffic_switcher.go @@ -676,6 +676,9 @@ func (wr *Wrangler) DropTargets(ctx context.Context, targetKeyspace, workflow st if err := wr.dropArtifacts(ctx, sw); err != nil { return nil, err } + if err := ts.wr.ts.RebuildSrvVSchema(ctx, nil); err != nil { + return nil, err + } return sw.logs(), nil } @@ -750,6 +753,10 @@ func (wr *Wrangler) DropSources(ctx context.Context, targetKeyspace, workflow st if err := wr.dropArtifacts(ctx, sw); err != nil { return nil, err } + if err := ts.wr.ts.RebuildSrvVSchema(ctx, nil); err != nil { + return nil, err + } + return sw.logs(), nil } @@ -1102,7 +1109,7 @@ func (ts *trafficSwitcher) changeTableSourceWrites(ctx context.Context, access a }); err != nil { return err } - return ts.wr.tmc.RefreshState(ctx, source.master.Tablet) + return ts.wr.RefreshTabletsByShard(ctx, source.si, nil, nil) }) } @@ -1337,7 +1344,7 @@ func (ts *trafficSwitcher) allowTableTargetWrites(ctx context.Context) error { }); err != nil { return err } - return ts.wr.tmc.RefreshState(ctx, target.master.Tablet) + return ts.wr.RefreshTabletsByShard(ctx, target.si, nil, nil) }) } @@ -1481,7 +1488,7 @@ func (ts *trafficSwitcher) dropSourceBlacklistedTables(ctx context.Context) erro }); err != nil { return err } - return ts.wr.tmc.RefreshState(ctx, source.master.Tablet) + return ts.wr.RefreshTabletsByShard(ctx, source.si, nil, nil) }) } diff --git a/go/vt/wrangler/traffic_switcher_test.go b/go/vt/wrangler/traffic_switcher_test.go index 092ce43fd18..8a8658c2dfa 100644 --- a/go/vt/wrangler/traffic_switcher_test.go +++ b/go/vt/wrangler/traffic_switcher_test.go @@ -915,10 +915,28 @@ func TestTableMigrateOneToMany(t *testing.T) { } dropSources() + checkRouting(t, tme.wr, map[string][]string{ + "t1": {"ks2.t1"}, + "ks1.t1": {"ks2.t1"}, + "t2": {"ks2.t2"}, + "ks1.t2": {"ks2.t2"}, + "t1@replica": {"ks2.t1"}, + "ks2.t1@replica": {"ks2.t1"}, + "ks1.t1@replica": {"ks2.t1"}, + "t2@replica": {"ks2.t2"}, + "ks2.t2@replica": {"ks2.t2"}, + "ks1.t2@replica": {"ks2.t2"}, + "t1@rdonly": {"ks2.t1"}, + "ks2.t1@rdonly": {"ks2.t1"}, + "ks1.t1@rdonly": {"ks2.t1"}, + "t2@rdonly": {"ks2.t2"}, + "ks2.t2@rdonly": {"ks2.t2"}, + "ks1.t2@rdonly": {"ks2.t2"}, + }) _, err = tme.wr.DropSources(ctx, tme.targetKeyspace, "test", RenameTable, false, false, false) require.NoError(t, err) checkBlacklist(t, tme.ts, fmt.Sprintf("%s:%s", "ks1", "0"), nil) - + checkRouting(t, tme.wr, map[string][]string{}) verifyQueries(t, tme.allDBClients) } From af9eadb3257a9a035211cedc102747364124eaa6 Mon Sep 17 00:00:00 2001 From: Dylan Visher Date: Mon, 3 May 2021 07:02:38 -0700 Subject: [PATCH 33/49] vreplication: fix vreplication timing metrics Several of the vreplication metrics were recently updated to no longer be correct. Specifically time.Now() is no longer executed when the function starts and is instead executed when the defer statement is called after the end of the function. This updates the metrics to properly execute time.Now() at the start of the functions. Signed-off-by: Dylan Visher --- .../vttablet/tabletmanager/vreplication/vcopier.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier.go index 43272b83cb2..352f941c8e8 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vcopier.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vcopier.go @@ -140,9 +140,7 @@ func (vc *vcopier) copyNext(ctx context.Context, settings binlogplayer.VRSetting func (vc *vcopier) catchup(ctx context.Context, copyState map[string]*sqltypes.Result) error { ctx, cancel := context.WithCancel(ctx) defer cancel() - defer func() { - vc.vr.stats.PhaseTimings.Record("catchup", time.Now()) - }() + defer vc.vr.stats.PhaseTimings.Record("catchup", time.Now()) settings, err := binlogplayer.ReadVRSettings(vc.vr.dbClient, vc.vr.id) if err != nil { @@ -192,10 +190,8 @@ func (vc *vcopier) catchup(ctx context.Context, copyState map[string]*sqltypes.R // committed with the lastpk. This allows for consistent resumability. func (vc *vcopier) copyTable(ctx context.Context, tableName string, copyState map[string]*sqltypes.Result) error { defer vc.vr.dbClient.Rollback() - defer func() { - vc.vr.stats.PhaseTimings.Record("copy", time.Now()) - vc.vr.stats.CopyLoopCount.Add(1) - }() + defer vc.vr.stats.PhaseTimings.Record("copy", time.Now()) + defer vc.vr.stats.CopyLoopCount.Add(1) log.Infof("Copying table %s, lastpk: %v", tableName, copyState[tableName]) @@ -321,9 +317,7 @@ func (vc *vcopier) copyTable(ctx context.Context, tableName string, copyState ma } func (vc *vcopier) fastForward(ctx context.Context, copyState map[string]*sqltypes.Result, gtid string) error { - defer func() { - vc.vr.stats.PhaseTimings.Record("fastforward", time.Now()) - }() + defer vc.vr.stats.PhaseTimings.Record("fastforward", time.Now()) pos, err := mysql.DecodePosition(gtid) if err != nil { return err From 5043c0f562b5261df46b5c73ad6b012975982026 Mon Sep 17 00:00:00 2001 From: Rohit Nayak Date: Tue, 27 Apr 2021 19:42:30 +0200 Subject: [PATCH 34/49] VReplication: Pad binlog values for binary() columns to match the value returned by mysql selects Backport of #7969 * Pad binlog values for binary() columns to match the value returned by a select query. This also ensures that if such columns are used as sharding keys we get the same keyspace_id * Pad binary() values in the binlog reader directly so that all consumers see the padded value instead of doing it later in vstreamer or doint it just for keyspace id computation Signed-off-by: Rohit Nayak Signed-off-by: Andres Taylor --- go/mysql/binlog_event_rbr.go | 12 ++++++++++ go/test/endtoend/vreplication/config.go | 22 ++++++++++++++----- go/test/endtoend/vreplication/helper.go | 3 +++ .../vreplication/unsharded_init_data.sql | 4 ++++ .../vreplication/vreplication_test.go | 6 ++++- .../vreplication/vreplication_test_env.go | 16 ++++++++------ .../vreplication/framework_test.go | 5 ++++- .../vreplication/table_plan_builder.go | 14 ++---------- .../vreplication/vcopier_test.go | 2 +- .../vreplication/vplayer_flaky_test.go | 18 +++++++-------- .../tabletserver/vstreamer/planbuilder.go | 6 ++--- .../tabletserver/vstreamer/vstreamer.go | 1 + .../tabletserver/vstreamer/vstreamer_test.go | 22 +++++++++---------- 13 files changed, 81 insertions(+), 50 deletions(-) diff --git a/go/mysql/binlog_event_rbr.go b/go/mysql/binlog_event_rbr.go index 7c2341a322a..906ccba5c39 100644 --- a/go/mysql/binlog_event_rbr.go +++ b/go/mysql/binlog_event_rbr.go @@ -895,6 +895,18 @@ func CellValue(data []byte, pos int, typ byte, metadata uint16, styp querypb.Typ l := int(data[pos]) mdata := data[pos+1 : pos+1+l] if sqltypes.IsBinary(styp) { + // For binary(n) column types, mysql pads the data on the right with nulls. However the binlog event contains + // the data without this padding. This causes several issues: + // * if a binary(n) column is part of the sharding key, the keyspace_id() returned during the copy phase + // (where the value is the result of a mysql query) is different from the one during replication + // (where the value is the one from the binlogs) + // * mysql where clause comparisons do not do the right thing without padding + // So for fixed length binary() columns we right-pad it with nulls if necessary + if l < max { + paddedData := make([]byte, max) + copy(paddedData[:l], mdata) + mdata = paddedData + } return sqltypes.MakeTrusted(querypb.Type_BINARY, mdata), l + 1, nil } return sqltypes.MakeTrusted(querypb.Type_VARCHAR, mdata), l + 1, nil diff --git a/go/test/endtoend/vreplication/config.go b/go/test/endtoend/vreplication/config.go index d937b7a4948..fc8a08e0958 100644 --- a/go/test/endtoend/vreplication/config.go +++ b/go/test/endtoend/vreplication/config.go @@ -10,6 +10,7 @@ create table orders(oid int, cid int, pid int, mname varchar(128), price int, pr create table order_seq(id int, next_id bigint, cache bigint, primary key(id)) comment 'vitess_sequence'; create table customer2(cid int, name varbinary(128), typ enum('individual','soho','enterprise'), sport set('football','cricket','baseball'),ts timestamp not null default current_timestamp, primary key(cid)); create table customer_seq2(id int, next_id bigint, cache bigint, primary key(id)) comment 'vitess_sequence'; +create table tenant(tenant_id binary(16), name varbinary(16), primary key (tenant_id)); ` initialProductVSchema = ` @@ -28,7 +29,8 @@ create table customer_seq2(id int, next_id bigint, cache bigint, primary key(id) }, "order_seq": { "type": "sequence" - } + }, + "tenant": {} } } ` @@ -39,9 +41,12 @@ create table customer_seq2(id int, next_id bigint, cache bigint, primary key(id) "vindexes": { "reverse_bits": { "type": "reverse_bits" - } + }, + "binary_md5": { + "type": "binary_md5" + } }, - "tables": { + "tables": { "customer": { "column_vindexes": [ { @@ -65,9 +70,16 @@ create table customer_seq2(id int, next_id bigint, cache bigint, primary key(id) "column": "cid", "sequence": "customer_seq2" } - } + }, + "tenant": { + "column_vindexes": [ + { + "column": "tenant_id", + "name": "binary_md5" + } + ] + } } - } ` merchantVSchema = ` diff --git a/go/test/endtoend/vreplication/helper.go b/go/test/endtoend/vreplication/helper.go index c2d69d1afea..6c9a8bdbb13 100644 --- a/go/test/endtoend/vreplication/helper.go +++ b/go/test/endtoend/vreplication/helper.go @@ -24,6 +24,9 @@ import ( func execMultipleQueries(t *testing.T, conn *mysql.Conn, database string, lines string) { queries := strings.Split(lines, "\n") for _, query := range queries { + if strings.HasPrefix(query, "--") { + continue + } execVtgateQuery(t, conn, database, string(query)) } } diff --git a/go/test/endtoend/vreplication/unsharded_init_data.sql b/go/test/endtoend/vreplication/unsharded_init_data.sql index f8e0cc5d86f..06eb2e18628 100644 --- a/go/test/endtoend/vreplication/unsharded_init_data.sql +++ b/go/test/endtoend/vreplication/unsharded_init_data.sql @@ -11,3 +11,7 @@ insert into orders(oid, cid, mname, pid, price) values(3, 2, 'monoprice', 2, 20) insert into customer2(cid, name, typ, sport) values(1, 'john',1,'football,baseball'); insert into customer2(cid, name, typ, sport) values(2, 'paul','soho','cricket'); insert into customer2(cid, name, typ, sport) values(3, 'ringo','enterprise',''); +-- for testing edge case where inserted binary value is 15 bytes, field is 16, mysql adds a null while storing but binlog returns 15 bytes +insert into tenant(tenant_id, name) values (x'02BD00987932461E8820C908E84BAE', 'abc'); + + diff --git a/go/test/endtoend/vreplication/vreplication_test.go b/go/test/endtoend/vreplication/vreplication_test.go index dde5228f238..c4ea174354a 100644 --- a/go/test/endtoend/vreplication/vreplication_test.go +++ b/go/test/endtoend/vreplication/vreplication_test.go @@ -72,6 +72,9 @@ func TestBasicVreplicationWorkflow(t *testing.T) { materializeRollup(t) shardCustomer(t, true, []*Cell{defaultCell}, defaultCellName) + // the tenant table was to test a specific case with binary sharding keys. Drop it now so that we don't + // have to update the rest of the tests + execVtgateQuery(t, vtgateConn, "customer", "drop table tenant") validateRollupReplicates(t) shardOrders(t) shardMerchant(t) @@ -198,7 +201,7 @@ func shardCustomer(t *testing.T, testReverse bool, cells []*Cell, sourceCellOrAl if err := vtgate.WaitForStatusOfTabletInShard(fmt.Sprintf("%s.%s.master", "customer", "80-"), 1); err != nil { t.Fatal(err) } - tables := "customer" + tables := "customer,tenant" moveTables(t, sourceCellOrAlias, workflow, sourceKs, targetKs, tables) // Assume we are operating on first cell @@ -216,6 +219,7 @@ func shardCustomer(t *testing.T, testReverse bool, cells []*Cell, sourceCellOrAl insertQuery1 := "insert into customer(cid, name) values(1001, 'tempCustomer1')" matchInsertQuery1 := "insert into customer(cid, `name`) values (:vtg1, :vtg2)" require.True(t, validateThatQueryExecutesOnTablet(t, vtgateConn, productTab, "product", insertQuery1, matchInsertQuery1)) + execVtgateQuery(t, vtgateConn, "product", "update tenant set name='xyz'") vdiff(t, ksWorkflow) switchReadsDryRun(t, allCellNames, ksWorkflow, dryRunResultsReadCustomerShard) switchReads(t, allCellNames, ksWorkflow) diff --git a/go/test/endtoend/vreplication/vreplication_test_env.go b/go/test/endtoend/vreplication/vreplication_test_env.go index e618432a7ef..4c53f5104b8 100644 --- a/go/test/endtoend/vreplication/vreplication_test_env.go +++ b/go/test/endtoend/vreplication/vreplication_test_env.go @@ -19,14 +19,14 @@ package vreplication var dryRunResultsSwitchWritesCustomerShard = []string{ "Lock keyspace product", "Lock keyspace customer", - "Stop writes on keyspace product, tables [customer]:", + "Stop writes on keyspace product, tables [customer,tenant]:", "/ Keyspace product, Shard 0 at Position", "Wait for VReplication on stopped streams to catchup for upto 30s", "Create reverse replication workflow p2c_reverse", "Create journal entries on source databases", - "Enable writes on keyspace customer tables [customer]", + "Enable writes on keyspace customer tables [customer,tenant]", "Switch routing from keyspace product to keyspace customer", - "Routing rules for tables [customer] will be updated", + "Routing rules for tables [customer,tenant] will be updated", "SwitchWrites completed, freeze and delete vreplication streams on:", " tablet 200 ", " tablet 300 ", @@ -41,8 +41,8 @@ var dryRunResultsSwitchWritesCustomerShard = []string{ var dryRunResultsReadCustomerShard = []string{ "Lock keyspace product", - "Switch reads for tables [customer] to keyspace customer for tablet types [REPLICA,RDONLY]", - "Routing rules for tables [customer] will be updated", + "Switch reads for tables [customer,tenant] to keyspace customer for tablet types [REPLICA,RDONLY]", + "Routing rules for tables [customer,tenant] will be updated", "Unlock keyspace product", } @@ -91,7 +91,8 @@ var dryRunResultsDropSourcesDropCustomerShard = []string{ "Lock keyspace customer", "Dropping these tables from the database and removing them from the vschema for keyspace product:", " Keyspace product Shard 0 DbName vt_product Tablet 100 Table customer", - "Blacklisted tables [customer] will be removed from:", + " Keyspace product Shard 0 DbName vt_product Tablet 100 Table tenant", + "Blacklisted tables [customer,tenant] will be removed from:", " Keyspace product Shard 0 Tablet 100", "Delete reverse vreplication streams on source:", " Keyspace product Shard 0 Workflow p2c_reverse DbName vt_product Tablet 100", @@ -108,7 +109,8 @@ var dryRunResultsDropSourcesRenameCustomerShard = []string{ "Lock keyspace customer", "Renaming these tables from the database and removing them from the vschema for keyspace product:", " Keyspace product Shard 0 DbName vt_product Tablet 100 Table customer", - "Blacklisted tables [customer] will be removed from:", + " Keyspace product Shard 0 DbName vt_product Tablet 100 Table tenant", + "Blacklisted tables [customer,tenant] will be removed from:", " Keyspace product Shard 0 Tablet 100", "Delete reverse vreplication streams on source:", " Keyspace product Shard 0 Workflow p2c_reverse DbName vt_product Tablet 100", diff --git a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go index d66f3a4c13d..ed3260c57ff 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/framework_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/framework_test.go @@ -121,12 +121,15 @@ func TestMain(m *testing.M) { playerEngine = NewTestEngine(env.TopoServ, env.Cells[0], env.Mysqld, realDBClientFactory, vrepldb, externalConfig) playerEngine.Open(context.Background()) defer playerEngine.Close() - if err := env.Mysqld.ExecuteSuperQueryList(context.Background(), binlogplayer.CreateVReplicationTable()); err != nil { fmt.Fprintf(os.Stderr, "%v", err) return 1 } + for _, query := range binlogplayer.AlterVReplicationTable { + env.Mysqld.ExecuteSuperQuery(context.Background(), query) + } + if err := env.Mysqld.ExecuteSuperQuery(context.Background(), createCopyState); err != nil { fmt.Fprintf(os.Stderr, "%v", err) return 1 diff --git a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go index d02c372469a..98c30acde97 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go +++ b/go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go @@ -674,16 +674,6 @@ func (tpb *tablePlanBuilder) generateDeleteStatement() *sqlparser.ParsedQuery { return buf.ParsedQuery() } -// For binary(n) column types, the value in the where clause needs to be padded with nulls upto the length of the column -// for MySQL comparison to work properly. This is achieved by casting it to the column type -func castIfNecessary(buf *sqlparser.TrackedBuffer, cexpr *colExpr) { - if cexpr.dataType == "binary" { - buf.Myprintf("cast(%v as %s)", cexpr.expr, cexpr.columnType) - return - } - buf.Myprintf("%v", cexpr.expr) -} - func (tpb *tablePlanBuilder) generateWhere(buf *sqlparser.TrackedBuffer, bvf *bindvarFormatter) { buf.WriteString(" where ") bvf.mode = bvBefore @@ -691,11 +681,11 @@ func (tpb *tablePlanBuilder) generateWhere(buf *sqlparser.TrackedBuffer, bvf *bi for _, cexpr := range tpb.pkCols { if _, ok := cexpr.expr.(*sqlparser.ColName); ok { buf.Myprintf("%s%v=", separator, cexpr.colName) - castIfNecessary(buf, cexpr) + buf.Myprintf("%v", cexpr.expr) } else { // Parenthesize non-trivial expressions. buf.Myprintf("%s%v=(", separator, cexpr.colName) - castIfNecessary(buf, cexpr) + buf.Myprintf("%v", cexpr.expr) buf.Myprintf(")") } separator = " and " diff --git a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go index 1ebdcad540a..6d372b83540 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vcopier_test.go @@ -121,7 +121,7 @@ func TestPlayerCopyCharPK(t *testing.T) { "/update _vt.vreplication set state='Copying'", "insert into dst(idc,val) values ('a\\0',1)", `/update _vt.copy_state set lastpk='fields: rows: ' where vrepl_id=.*`, - `update dst set val=3 where idc=cast('a' as binary(2)) and ('a') <= ('a\0')`, + `update dst set val=3 where idc='a\0' and ('a\0') <= ('a\0')`, "insert into dst(idc,val) values ('c\\0',2)", `/update _vt.copy_state set lastpk='fields: rows: ' where vrepl_id=.*`, "/delete from _vt.copy_state.*dst", diff --git a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go index adf55a3f80f..374e2acbe0c 100644 --- a/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go +++ b/go/vt/vttablet/tabletmanager/vreplication/vplayer_flaky_test.go @@ -148,14 +148,14 @@ func TestCharPK(t *testing.T) { data [][]string }{{ //binary(2) input: "insert into t1 values(1, 'a')", - output: "insert into t1(id,val) values (1,'a')", + output: "insert into t1(id,val) values (1,'a\\0')", table: "t1", data: [][]string{ {"1", "a\000"}, }, }, { input: "update t1 set id = 2 where val = 'a\000'", - output: "update t1 set id=2 where val=cast('a' as binary(2))", + output: "update t1 set id=2 where val='a\\0'", table: "t1", data: [][]string{ {"2", "a\000"}, @@ -1278,8 +1278,8 @@ func TestPlayerTypes(t *testing.T) { fmt.Sprintf("create table %s.vitess_ints(tiny tinyint, tinyu tinyint unsigned, small smallint, smallu smallint unsigned, medium mediumint, mediumu mediumint unsigned, normal int, normalu int unsigned, big bigint, bigu bigint unsigned, y year, primary key(tiny))", vrepldb), "create table vitess_fracts(id int, deci decimal(5,2), num numeric(5,2), f float, d double, primary key(id))", fmt.Sprintf("create table %s.vitess_fracts(id int, deci decimal(5,2), num numeric(5,2), f float, d double, primary key(id))", vrepldb), - "create table vitess_strings(vb varbinary(16), c char(16), vc varchar(16), b binary(4), tb tinyblob, bl blob, ttx tinytext, tx text, en enum('a','b'), s set('a','b'), primary key(vb))", - fmt.Sprintf("create table %s.vitess_strings(vb varbinary(16), c char(16), vc varchar(16), b binary(4), tb tinyblob, bl blob, ttx tinytext, tx text, en enum('a','b'), s set('a','b'), primary key(vb))", vrepldb), + "create table vitess_strings(vb varbinary(16), c char(16), vc varchar(16), b binary(5), tb tinyblob, bl blob, ttx tinytext, tx text, en enum('a','b'), s set('a','b'), primary key(vb))", + fmt.Sprintf("create table %s.vitess_strings(vb varbinary(16), c char(16), vc varchar(16), b binary(5), tb tinyblob, bl blob, ttx tinytext, tx text, en enum('a','b'), s set('a','b'), primary key(vb))", vrepldb), "create table vitess_misc(id int, b bit(8), d date, dt datetime, t time, g geometry, primary key(id))", fmt.Sprintf("create table %s.vitess_misc(id int, b bit(8), d date, dt datetime, t time, g geometry, primary key(id))", vrepldb), "create table vitess_null(id int, val varbinary(128), primary key(id))", @@ -1351,10 +1351,10 @@ func TestPlayerTypes(t *testing.T) { }, }, { input: "insert into vitess_strings values('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'a,b')", - output: "insert into vitess_strings(vb,c,vc,b,tb,bl,ttx,tx,en,s) values ('a','b','c','d','e','f','g','h','1','3')", + output: "insert into vitess_strings(vb,c,vc,b,tb,bl,ttx,tx,en,s) values ('a','b','c','d\\0\\0\\0\\0','e','f','g','h','1','3')", table: "vitess_strings", data: [][]string{ - {"a", "b", "c", "d\000\000\000", "e", "f", "g", "h", "a", "a,b"}, + {"a", "b", "c", "d\000\000\000\000", "e", "f", "g", "h", "a", "a,b"}, }, }, { input: "insert into vitess_misc values(1, '\x01', '2012-01-01', '2012-01-01 15:45:45', '15:45:45', point(1, 2))", @@ -1372,7 +1372,7 @@ func TestPlayerTypes(t *testing.T) { }, }, { input: "insert into binary_pk values('a', 'aaa')", - output: "insert into binary_pk(b,val) values ('a','aaa')", + output: "insert into binary_pk(b,val) values ('a\\0\\0\\0','aaa')", table: "binary_pk", data: [][]string{ {"a\000\000\000", "aaa"}, @@ -1380,10 +1380,10 @@ func TestPlayerTypes(t *testing.T) { }, { // Binary pk is a special case: https://github.com/vitessio/vitess/issues/3984 input: "update binary_pk set val='bbb' where b='a\\0\\0\\0'", - output: "update binary_pk set val='bbb' where b=cast('a' as binary(4))", + output: "update binary_pk set val='bbb' where b='a\\0\\0\\0'", table: "binary_pk", data: [][]string{ - {"a\x00\x00\x00", "bbb"}, + {"a\000\000\000", "bbb"}, }, }} diff --git a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go index 3454183b069..35ce57eb6f3 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go +++ b/go/vt/vttablet/tabletserver/vstreamer/planbuilder.go @@ -122,7 +122,7 @@ func (plan *Plan) filter(values []sqltypes.Value) (bool, []sqltypes.Value, error return false, nil, nil } case VindexMatch: - ksid, err := getKeyspaceID(values, filter.Vindex, filter.VindexColumns) + ksid, err := getKeyspaceID(values, filter.Vindex, filter.VindexColumns, plan.Table.Fields) if err != nil { return false, nil, err } @@ -144,7 +144,7 @@ func (plan *Plan) filter(values []sqltypes.Value) (bool, []sqltypes.Value, error if colExpr.Vindex == nil { result[i] = values[colExpr.ColNum] } else { - ksid, err := getKeyspaceID(values, colExpr.Vindex, colExpr.VindexColumns) + ksid, err := getKeyspaceID(values, colExpr.Vindex, colExpr.VindexColumns, plan.Table.Fields) if err != nil { return false, nil, err } @@ -154,7 +154,7 @@ func (plan *Plan) filter(values []sqltypes.Value) (bool, []sqltypes.Value, error return true, result, nil } -func getKeyspaceID(values []sqltypes.Value, vindex vindexes.Vindex, vindexColumns []int) (key.DestinationKeyspaceID, error) { +func getKeyspaceID(values []sqltypes.Value, vindex vindexes.Vindex, vindexColumns []int, fields []*querypb.Field) (key.DestinationKeyspaceID, error) { vindexValues := make([]sqltypes.Value, 0, len(vindexColumns)) for _, col := range vindexColumns { vindexValues = append(vindexValues, values[col]) diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go index b9eb23f7ef7..fb0333da33d 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer.go @@ -862,6 +862,7 @@ func (vs *vstreamer) extractRowAndFilter(plan *streamerPlan, data []byte, dataCo return false, nil, err } pos += l + values[colNum] = value valueIndex++ } diff --git a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go index 4851b685b2f..b1e4aa23651 100644 --- a/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go +++ b/go/vt/vttablet/tabletserver/vstreamer/vstreamer_test.go @@ -110,9 +110,9 @@ func TestSetAndEnum(t *testing.T) { output: [][]string{{ `begin`, fe.String(), - `type:ROW row_event: > > `, - `type:ROW row_event: > > `, - `type:ROW row_event: > > `, + `type:ROW row_event: > > `, + `type:ROW row_event: > > `, + `type:ROW row_event: > > `, `gtid`, `commit`, }}, @@ -133,8 +133,8 @@ func TestCellValuePadding(t *testing.T) { engine.se.Reload(context.Background()) queries := []string{ "begin", - "insert into t1 values (1, 'aaa')", - "insert into t1 values (2, 'bbb')", + "insert into t1 values (1, 'aaa\000')", + "insert into t1 values (2, 'bbb\000')", "update t1 set id = 11 where val = 'aaa\000'", "insert into t2 values (1, 'aaa')", "insert into t2 values (2, 'bbb')", @@ -147,9 +147,9 @@ func TestCellValuePadding(t *testing.T) { output: [][]string{{ `begin`, `type:FIELD field_event: fields: > `, - `type:ROW row_event: > > `, - `type:ROW row_event: > > `, - `type:ROW row_event: after: > > `, + `type:ROW row_event: > > `, + `type:ROW row_event: > > `, + `type:ROW row_event: after: > > `, `type:FIELD field_event: fields: > `, `type:ROW row_event: > > `, `type:ROW row_event: > > `, @@ -1561,13 +1561,13 @@ func TestTypes(t *testing.T) { }, { // TODO(sougou): validate that binary and char data generate correct DMLs on the other end. input: []string{ - "insert into vitess_strings values('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'a', 'a,b')", + "insert into vitess_strings values('a', 'b', 'c', 'd\000\000\000', 'e', 'f', 'g', 'h', 'a', 'a,b')", }, output: [][]string{{ `begin`, `type:FIELD field_event: fields: fields: fields: fields: fields: fields: fields: fields: fields: > `, - `type:ROW row_event: > > `, + `type:ROW row_event: > > `, `gtid`, `commit`, }}, From 3c192cb11b5bd770de0e5bb6056fdb248fe6023d Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Fri, 30 Apr 2021 13:15:17 +0530 Subject: [PATCH 35/49] ignore the error and log as warn if not able to validate the current system settings value Signed-off-by: Harshit Gangal --- go/vt/vtgate/engine/set.go | 6 +++++- go/vt/vtgate/engine/set_test.go | 26 ++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/go/vt/vtgate/engine/set.go b/go/vt/vtgate/engine/set.go index 43401cb8a25..dc317e52a23 100644 --- a/go/vt/vtgate/engine/set.go +++ b/go/vt/vtgate/engine/set.go @@ -247,7 +247,11 @@ func (svci *SysVarCheckAndIgnore) Execute(vcursor VCursor, env evalengine.Expres checkSysVarQuery := fmt.Sprintf("select 1 from dual where @@%s = %s", svci.Name, svci.Expr) result, err := execShard(vcursor, checkSysVarQuery, env.BindVars, rss[0], false /* rollbackOnError */, false /* canAutocommit */) if err != nil { - return err + // Rather than returning the error, we will just log the error + // as the intention for executing the query it to validate the current setting and eventually ignore it anyways. + // There is no benefit of returning the error back to client. + log.Warningf("unable to validate the current settings for '%s': %s", svci.Name, err.Error()) + return nil } if result.RowsAffected == 0 { log.Infof("Ignored inapplicable SET %v = %v", svci.Name, svci.Expr) diff --git a/go/vt/vtgate/engine/set_test.go b/go/vt/vtgate/engine/set_test.go index ce2c0bae504..e6a3b0f45ad 100644 --- a/go/vt/vtgate/engine/set_test.go +++ b/go/vt/vtgate/engine/set_test.go @@ -17,6 +17,7 @@ limitations under the License. package engine import ( + "errors" "fmt" "testing" @@ -74,6 +75,7 @@ func TestSetTable(t *testing.T) { expectedWarning []*querypb.QueryWarning expectedError string input Primitive + execErr error } tests := []testCase{ @@ -193,6 +195,25 @@ func TestSetTable(t *testing.T) { }, expectedError: "Unexpected error, DestinationKeyspaceID mapping to multiple shards: DestinationAllShards()", }, + { + testName: "sysvar checkAndIgnore execute error", + setOps: []SetOp{ + &SysVarCheckAndIgnore{ + Name: "x", + Keyspace: &vindexes.Keyspace{ + Name: "ks", + Sharded: true, + }, + TargetDestination: key.DestinationAnyShard{}, + Expr: "dummy_expr", + }, + }, + expectedQueryLog: []string{ + `ResolveDestinations ks [] Destinations:DestinationAnyShard()`, + `ExecuteMultiShard ks.-20: select 1 from dual where @@x = dummy_expr {} false false`, + }, + execErr: errors.New("some random error"), + }, { testName: "udv ignore checkAndIgnore ", setOps: []SetOp{ @@ -299,8 +320,9 @@ func TestSetTable(t *testing.T) { Input: tc.input, } vc := &loggingVCursor{ - shards: []string{"-20", "20-"}, - results: tc.qr, + shards: []string{"-20", "20-"}, + results: tc.qr, + multiShardErrs: []error{tc.execErr}, } _, err := set.Execute(vc, map[string]*querypb.BindVariable{}, false) if tc.expectedError == "" { From 036f4efb8ccd0d52f739237f0c5490022ddc969b Mon Sep 17 00:00:00 2001 From: deepthi Date: Fri, 26 Feb 2021 16:17:22 -0800 Subject: [PATCH 36/49] restore: do not restart replication if disable_active_reparents is set. Also, Begin and End Maintenance on orchestrator backup: do not restart replication if disable_active_reparents is set. Also, Begin and End Maintenance on orchestrator Signed-off-by: deepthi Signed-off-by: Florent Poinsard --- go/vt/mysqlctl/builtinbackupengine.go | 2 +- go/vt/vttablet/tabletmanager/restore.go | 30 +++- go/vt/vttablet/tabletmanager/rpc_backup.go | 20 +++ go/vt/vttablet/tabletmanager/tm_init.go | 5 +- go/vt/wrangler/testlib/backup_test.go | 151 +++++++++++++++++++++ 5 files changed, 201 insertions(+), 7 deletions(-) diff --git a/go/vt/mysqlctl/builtinbackupengine.go b/go/vt/mysqlctl/builtinbackupengine.go index b064ad2d677..1e727f5afcf 100644 --- a/go/vt/mysqlctl/builtinbackupengine.go +++ b/go/vt/mysqlctl/builtinbackupengine.go @@ -152,7 +152,7 @@ func (be *BuiltinBackupEngine) ExecuteBackup(ctx context.Context, params BackupP replicaStatus, err := params.Mysqld.ReplicationStatus() switch err { case nil: - replicaStartRequired = replicaStatus.ReplicationRunning() + replicaStartRequired = replicaStatus.ReplicationRunning() && !*DisableActiveReparents case mysql.ErrNotReplica: // keep going if we're the master, might be a degenerate case sourceIsMaster = true diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index 63408eb62ba..790b41fed65 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -78,7 +78,28 @@ func (tm *TabletManager) RestoreData(ctx context.Context, logger logutil.Logger, if tm.Cnf == nil { return fmt.Errorf("cannot perform restore without my.cnf, please restart vttablet with a my.cnf file specified") } - return tm.restoreDataLocked(ctx, logger, waitForBackupInterval, deleteBeforeRestore) + // Tell Orchestrator we're stopped on purpose for some Vitess task. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.BeginMaintenance(tm.Tablet(), "vttablet has been told to Restore"); err != nil { + log.Warningf("Orchestrator BeginMaintenance failed: %v", err) + } + }() + err := tm.restoreDataLocked(ctx, logger, waitForBackupInterval, deleteBeforeRestore) + // Tell Orchestrator we're no longer stopped on purpose. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.EndMaintenance(tm.Tablet()); err != nil { + log.Warningf("Orchestrator EndMaintenance failed: %v", err) + } + }() + return err } func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.Logger, waitForBackupInterval time.Duration, deleteBeforeRestore bool) error { @@ -470,10 +491,15 @@ func (tm *TabletManager) startReplication(ctx context.Context, pos mysql.Positio } // Set master and start replication. - if err := tm.MysqlDaemon.SetMaster(ctx, ti.Tablet.MysqlHostname, int(ti.Tablet.MysqlPort), false /* stopReplicationBefore */, true /* startReplicationAfter */); err != nil { + if err := tm.MysqlDaemon.SetMaster(ctx, ti.Tablet.MysqlHostname, int(ti.Tablet.MysqlPort), false /* stopReplicationBefore */, !*mysqlctl.DisableActiveReparents /* startReplicationAfter */); err != nil { return vterrors.Wrap(err, "MysqlDaemon.SetMaster failed") } + // If active reparents are disabled, we don't restart replication. So it makes no sense to wait for an update on the replica. + // Return immediately. + if !*mysqlctl.DisableActiveReparents { + return nil + } // wait for reliable seconds behind master // we have pos where we want to resume from // if MasterPosition is the same, that means no writes diff --git a/go/vt/vttablet/tabletmanager/rpc_backup.go b/go/vt/vttablet/tabletmanager/rpc_backup.go index f4b65834197..683d69b2064 100644 --- a/go/vt/vttablet/tabletmanager/rpc_backup.go +++ b/go/vt/vttablet/tabletmanager/rpc_backup.go @@ -88,6 +88,16 @@ func (tm *TabletManager) Backup(ctx context.Context, concurrency int, logger log if err := tm.changeTypeLocked(ctx, topodatapb.TabletType_BACKUP, DBActionNone); err != nil { return err } + // Tell Orchestrator we're stopped on purpose for some Vitess task. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.BeginMaintenance(tm.Tablet(), "vttablet has been told to run an offline backup"); err != nil { + logger.Warningf("Orchestrator BeginMaintenance failed: %v", err) + } + }() } // create the loggers: tee to console and source l := logutil.NewTeeLogger(logutil.NewConsoleLogger(), logger) @@ -124,6 +134,16 @@ func (tm *TabletManager) Backup(ctx context.Context, concurrency int, logger log } returnErr = err } + // Tell Orchestrator we're no longer stopped on purpose. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.EndMaintenance(tm.Tablet()); err != nil { + logger.Warningf("Orchestrator EndMaintenance failed: %v", err) + } + }() } return returnErr diff --git a/go/vt/vttablet/tabletmanager/tm_init.go b/go/vt/vttablet/tabletmanager/tm_init.go index 6c9734b3ffb..e1d7d6757d2 100644 --- a/go/vt/vttablet/tabletmanager/tm_init.go +++ b/go/vt/vttablet/tabletmanager/tm_init.go @@ -597,10 +597,7 @@ func (tm *TabletManager) handleRestore(ctx context.Context) (bool, error) { return false, fmt.Errorf("you cannot enable -restore_from_backup without a my.cnf file") } - // two cases then: - // - restoreFromBackup is set: we restore, then initHealthCheck, all - // in the background - // - restoreFromBackup is not set: we initHealthCheck right away + // Restore in the background if *restoreFromBackup { go func() { // Open the state manager after restore is done. diff --git a/go/vt/wrangler/testlib/backup_test.go b/go/vt/wrangler/testlib/backup_test.go index 3d997d92ce0..c33437a4c1d 100644 --- a/go/vt/wrangler/testlib/backup_test.go +++ b/go/vt/wrangler/testlib/backup_test.go @@ -394,3 +394,154 @@ func TestRestoreUnreachableMaster(t *testing.T) { assert.True(t, destTablet.FakeMysqlDaemon.Replicating) assert.True(t, destTablet.FakeMysqlDaemon.Running) } + +func TestDisableActiveReparents(t *testing.T) { + *mysqlctl.DisableActiveReparents = true + delay := discovery.GetTabletPickerRetryDelay() + defer func() { + // When you mess with globals you must remember to reset them + *mysqlctl.DisableActiveReparents = false + discovery.SetTabletPickerRetryDelay(delay) + }() + discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) + + // Initialize our environment + ctx := context.Background() + db := fakesqldb.New(t) + defer db.Close() + ts := memorytopo.NewServer("cell1", "cell2") + wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) + vp := NewVtctlPipe(t, ts) + defer vp.Close() + + // Set up mock query results. + db.AddQuery("CREATE DATABASE IF NOT EXISTS _vt", &sqltypes.Result{}) + db.AddQuery("BEGIN", &sqltypes.Result{}) + db.AddQuery("COMMIT", &sqltypes.Result{}) + db.AddQueryPattern(`SET @@session\.sql_log_bin = .*`, &sqltypes.Result{}) + db.AddQueryPattern(`CREATE TABLE IF NOT EXISTS _vt\.shard_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`CREATE TABLE IF NOT EXISTS _vt\.local_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`ALTER TABLE _vt\.local_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`ALTER TABLE _vt\.shard_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`UPDATE _vt\.local_metadata SET db_name=.*`, &sqltypes.Result{}) + db.AddQueryPattern(`UPDATE _vt\.shard_metadata SET db_name=.*`, &sqltypes.Result{}) + db.AddQueryPattern(`INSERT INTO _vt\.local_metadata .*`, &sqltypes.Result{}) + + // Initialize our temp dirs + root, err := ioutil.TempDir("", "backuptest") + require.NoError(t, err) + defer os.RemoveAll(root) + + // Initialize BackupStorage + fbsRoot := path.Join(root, "fbs") + *filebackupstorage.FileBackupStorageRoot = fbsRoot + *backupstorage.BackupStorageImplementation = "file" + + // Initialize the fake mysql root directories + sourceInnodbDataDir := path.Join(root, "source_innodb_data") + sourceInnodbLogDir := path.Join(root, "source_innodb_log") + sourceDataDir := path.Join(root, "source_data") + sourceDataDbDir := path.Join(sourceDataDir, "vt_db") + for _, s := range []string{sourceInnodbDataDir, sourceInnodbLogDir, sourceDataDbDir} { + require.NoError(t, os.MkdirAll(s, os.ModePerm)) + } + require.NoError(t, ioutil.WriteFile(path.Join(sourceInnodbDataDir, "innodb_data_1"), []byte("innodb data 1 contents"), os.ModePerm)) + require.NoError(t, ioutil.WriteFile(path.Join(sourceInnodbLogDir, "innodb_log_1"), []byte("innodb log 1 contents"), os.ModePerm)) + require.NoError(t, ioutil.WriteFile(path.Join(sourceDataDbDir, "db.opt"), []byte("db opt file"), os.ModePerm)) + + // create a master tablet, set its master position + master := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_MASTER, db) + master.FakeMysqlDaemon.ReadOnly = false + master.FakeMysqlDaemon.Replicating = false + master.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + + // start master so that replica can fetch master position from it + master.StartActionLoop(t, wr) + defer master.StopActionLoop(t) + + // create a single tablet, set it up so we can do backups + // set its position same as that of master so that backup doesn't wait for catchup + sourceTablet := NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, db) + sourceTablet.FakeMysqlDaemon.ReadOnly = true + sourceTablet.FakeMysqlDaemon.Replicating = true + sourceTablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + sourceTablet.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP SLAVE", + } + sourceTablet.StartActionLoop(t, wr) + defer sourceTablet.StopActionLoop(t) + + sourceTablet.TM.Cnf = &mysqlctl.Mycnf{ + DataDir: sourceDataDir, + InnodbDataHomeDir: sourceInnodbDataDir, + InnodbLogGroupHomeDir: sourceInnodbLogDir, + } + + // run the backup + require.NoError(t, vp.Run([]string{"Backup", topoproto.TabletAliasString(sourceTablet.Tablet.Alias)})) + + // verify the full status + require.NoError(t, sourceTablet.FakeMysqlDaemon.CheckSuperQueryList()) + assert.False(t, sourceTablet.FakeMysqlDaemon.Replicating) + assert.True(t, sourceTablet.FakeMysqlDaemon.Running) + + // create a destination tablet, set it up so we can do restores + destTablet := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, db) + destTablet.FakeMysqlDaemon.ReadOnly = true + destTablet.FakeMysqlDaemon.Replicating = true + destTablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + destTablet.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP SLAVE", + "RESET SLAVE ALL", + "FAKE SET SLAVE POSITION", + "FAKE SET MASTER", + } + destTablet.FakeMysqlDaemon.FetchSuperQueryMap = map[string]*sqltypes.Result{ + "SHOW DATABASES": {}, + } + destTablet.FakeMysqlDaemon.SetReplicationPositionPos = sourceTablet.FakeMysqlDaemon.CurrentMasterPosition + destTablet.FakeMysqlDaemon.SetMasterInput = topoproto.MysqlAddr(master.Tablet) + + destTablet.StartActionLoop(t, wr) + defer destTablet.StopActionLoop(t) + + destTablet.TM.Cnf = &mysqlctl.Mycnf{ + DataDir: sourceDataDir, + InnodbDataHomeDir: sourceInnodbDataDir, + InnodbLogGroupHomeDir: sourceInnodbLogDir, + BinLogPath: path.Join(root, "bin-logs/filename_prefix"), + RelayLogPath: path.Join(root, "relay-logs/filename_prefix"), + RelayLogIndexPath: path.Join(root, "relay-log.index"), + RelayLogInfoPath: path.Join(root, "relay-log.info"), + } + + require.NoError(t, destTablet.TM.RestoreData(ctx, logutil.NewConsoleLogger(), 0 /* waitForBackupInterval */, false /* deleteBeforeRestore */)) + // verify the full status + require.NoError(t, destTablet.FakeMysqlDaemon.CheckSuperQueryList(), "destTablet.FakeMysqlDaemon.CheckSuperQueryList failed") + assert.False(t, destTablet.FakeMysqlDaemon.Replicating) + assert.True(t, destTablet.FakeMysqlDaemon.Running) +} From 42c38e56e4ae29012a5d603d8bc8c22c35b78b52 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 May 2021 16:55:49 +0200 Subject: [PATCH 37/49] Release commit for 9.0.1 Signed-off-by: Andres Taylor --- doc/releasenotes/9_0_1_release_notes.md | 38 +++++++++++++++++++++++++ java/client/pom.xml | 2 +- java/example/pom.xml | 2 +- java/grpc-client/pom.xml | 2 +- java/jdbc/pom.xml | 2 +- java/pom.xml | 2 +- 6 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 doc/releasenotes/9_0_1_release_notes.md diff --git a/doc/releasenotes/9_0_1_release_notes.md b/doc/releasenotes/9_0_1_release_notes.md new file mode 100644 index 00000000000..b60f59042a5 --- /dev/null +++ b/doc/releasenotes/9_0_1_release_notes.md @@ -0,0 +1,38 @@ +This release complies with VEP-3 which removes the upgrade order requirement. Components can be upgraded in any order. It is recommended that the upgrade order should still be followed if possible, except to canary test the new version of VTGate before upgrading the rest of the components. + +## Bug fixes +### Cluster management + * Backport: Respect -disable_active_reparents in backup/restore #8063 +### Other + * [9.0] fix regression - should be able to plan subquery on top of subquery #7683 +### Query Serving + * [9.0] Fix for reserved connection usage with transaction #7666 + * [9.0] Fix MySQL Workbench failure on login with `select current_user()` #7706 + * [9.0] make sure to handle subqueries on top of subqueries #7776 + * [9.0] make sure to not log sensitive information #7778 + * [9.0] ddl bypass planner #8035 + * [9.0] Memory Sort to close the goroutines when callback returns error #8040 + * [9.0] Fix bug with reserved connections to stale tablets #8041 + * [9.0] Fix for Query Serving when Toposerver is Down #8046 + * ignore the error and log as warn if not able to validate the current system settings value #8062 +### VReplication + * VReplication: fix vreplication timing metrics #8060 + * VReplication: Pad binlog values for binary() columns to match the value returned by mysql selects #8061 +## Documentation +### Other + * 9.0.0 Release Notes #7384 +## Other +### Build/CI + * Fix Dockerfiles for vtexplain and vtctlclient #7418 +### Query Serving + * Fix table parsing on VSchema generation #7511 + * [9.0] Show anywhere plan fix to consider default keyspace #7530 + * [9.0] Reset Session for Reserved Connection when the connection id is not found #7544 + * Healthcheck: update healthy tablets correctly when a stream returns an error or times out #7732 +### VReplication + * MoveTables: Refresh SrvVSchema and source tablets on completion #8059 + + +The release includes 43 commits (excluding merges) +Thanks to all our contributors: @askdba, @deepthi, @dyv, @harshit-gangal, @rafael, @rohit-nayak-ps, @shlomi-noach, @systay + diff --git a/java/client/pom.xml b/java/client/pom.xml index ca4cac809b7..6a3d498b4c9 100644 --- a/java/client/pom.xml +++ b/java/client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.0 + 9.0.1 vitess-client diff --git a/java/example/pom.xml b/java/example/pom.xml index d691745622e..df241e866e1 100644 --- a/java/example/pom.xml +++ b/java/example/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.0 + 9.0.1 vitess-example diff --git a/java/grpc-client/pom.xml b/java/grpc-client/pom.xml index 9209c9f480b..3e597229119 100644 --- a/java/grpc-client/pom.xml +++ b/java/grpc-client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.0 + 9.0.1 vitess-grpc-client diff --git a/java/jdbc/pom.xml b/java/jdbc/pom.xml index 8fbede6e6b4..ec1756cdfac 100644 --- a/java/jdbc/pom.xml +++ b/java/jdbc/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.0 + 9.0.1 vitess-jdbc diff --git a/java/pom.xml b/java/pom.xml index 4b469b9efbf..53ab1696082 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -11,7 +11,7 @@ io.vitess vitess-parent - 9.0.0 + 9.0.1 pom Vitess Java Client libraries [Parent] From 83f1e34d273a04838f78fecdbfa3448f2a2e09e7 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Thu, 6 May 2021 16:59:40 +0200 Subject: [PATCH 38/49] Back to dev mode Signed-off-by: Andres Taylor --- java/client/pom.xml | 2 +- java/example/pom.xml | 2 +- java/grpc-client/pom.xml | 2 +- java/jdbc/pom.xml | 2 +- java/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/java/client/pom.xml b/java/client/pom.xml index 6a3d498b4c9..188cea73f35 100644 --- a/java/client/pom.xml +++ b/java/client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.1 + 9.0.2-SNAPSHOT vitess-client diff --git a/java/example/pom.xml b/java/example/pom.xml index df241e866e1..ceef8a55a18 100644 --- a/java/example/pom.xml +++ b/java/example/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.1 + 9.0.2-SNAPSHOT vitess-example diff --git a/java/grpc-client/pom.xml b/java/grpc-client/pom.xml index 3e597229119..f53519e6e28 100644 --- a/java/grpc-client/pom.xml +++ b/java/grpc-client/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.1 + 9.0.2-SNAPSHOT vitess-grpc-client diff --git a/java/jdbc/pom.xml b/java/jdbc/pom.xml index ec1756cdfac..c6c2a629c91 100644 --- a/java/jdbc/pom.xml +++ b/java/jdbc/pom.xml @@ -5,7 +5,7 @@ io.vitess vitess-parent - 9.0.1 + 9.0.2-SNAPSHOT vitess-jdbc diff --git a/java/pom.xml b/java/pom.xml index 53ab1696082..16c1a4b4915 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -11,7 +11,7 @@ io.vitess vitess-parent - 9.0.1 + 9.0.2-SNAPSHOT pom Vitess Java Client libraries [Parent] From 09a29561d631c4bf1324c0a78d3df2a888522367 Mon Sep 17 00:00:00 2001 From: deepthi Date: Fri, 7 May 2021 15:29:15 -0700 Subject: [PATCH 39/49] 9.0.0: update release notes with known issue #8080 Signed-off-by: deepthi --- doc/releasenotes/9_0_0_release_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/releasenotes/9_0_0_release_notes.md b/doc/releasenotes/9_0_0_release_notes.md index 7d8b5f99e24..20c18b0a32f 100644 --- a/doc/releasenotes/9_0_0_release_notes.md +++ b/doc/releasenotes/9_0_0_release_notes.md @@ -7,6 +7,9 @@ The following PRs made changes to behaviors that clients might rely on. They sho Vitess 9.0 is not compatible with the previous release of the Vitess Kubernetes Operator (2.2.0). A new version of the Operator (2.3.0) is available that is compatible. +## Known Issue(s) +* VReplication errors when a fixed-length binary column is used as the sharding key #8080 + ## Bugs Fixed ### VTGate / MySQL compatibility From 5174796970daac0b59964d92503ed4702729d57e Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 2 Feb 2021 14:22:07 +0530 Subject: [PATCH 40/49] Fix information_schema query with system schema in table_schema filter Backport of #7430 This is a combination of 6 commits. * added system schema in where clause plan test * added executor unit test * added logic to check table_schema of where clause and redirect to default route if it is a system schema * added e2e test * set the bindvars for the normalized predicates and remove schema name from bv if tablet will replace it * added e2e test having table_schema and table_name in where clause Signed-off-by: Harshit Gangal Signed-off-by: Andres Taylor --- go/test/endtoend/vtgate/system_schema_test.go | 12 +- go/vt/vtgate/engine/route.go | 69 +++-- go/vt/vtgate/executor_select_test.go | 275 +++++------------- .../planbuilder/testdata/from_cases.txt | 18 ++ 4 files changed, 145 insertions(+), 229 deletions(-) diff --git a/go/test/endtoend/vtgate/system_schema_test.go b/go/test/endtoend/vtgate/system_schema_test.go index e5a100bd935..5954ee5af76 100644 --- a/go/test/endtoend/vtgate/system_schema_test.go +++ b/go/test/endtoend/vtgate/system_schema_test.go @@ -71,9 +71,13 @@ func TestInformationSchemaQuery(t *testing.T) { require.NoError(t, err) defer conn.Close() - assertSingleRowIsReturned(t, conn, "table_schema = 'ks'") - assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks'") + assertSingleRowIsReturned(t, conn, "table_schema = 'ks'", "vt_ks") + assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks'", "vt_ks") assertResultIsEmpty(t, conn, "table_schema = 'NONE'") + assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema'", "performance_schema") + assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'") + assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema") + assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'") } func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) { @@ -84,12 +88,12 @@ func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) { }) } -func assertSingleRowIsReturned(t *testing.T, conn *mysql.Conn, predicate string) { +func assertSingleRowIsReturned(t *testing.T, conn *mysql.Conn, predicate string, expectedKs string) { t.Run(predicate, func(t *testing.T) { qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+predicate, 1000, true) require.NoError(t, err) assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back") - assert.Equal(t, "vt_ks", qr.Rows[0][0].ToString()) + assert.Equal(t, expectedKs, qr.Rows[0][0].ToString()) }) } diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 71067fa51a9..61407b556f2 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -417,53 +417,59 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q Row: []sqltypes.Value{}, } + var specifiedKS string + if route.SysTableTableSchema != nil { + result, err := route.SysTableTableSchema.Evaluate(env) + if err != nil { + return nil, err + } + specifiedKS = result.Value().ToString() + bindVars[sqltypes.BvSchemaName] = sqltypes.StringBindVariable(specifiedKS) + } + + var tableName string if route.SysTableTableName != nil { - // the use has specified a table_name - let's check if it's a routed table - rss, err := route.paramsRoutedTable(vcursor, env, bindVars) + val, err := route.SysTableTableName.Evaluate(env) + if err != nil { + return nil, err + } + tableName = val.Value().ToString() + bindVars[BvTableName] = sqltypes.StringBindVariable(tableName) + } + + // if the table_schema is system system, route to default keyspace. + if sqlparser.SystemSchema(specifiedKS) { + return defaultRoute() + } + + // the use has specified a table_name - let's check if it's a routed table + if tableName != "" { + rss, err := route.paramsRoutedTable(vcursor, bindVars, specifiedKS, tableName) if err != nil { return nil, err } if rss != nil { return rss, nil } - // it was not a routed table, and we dont have a schema name to look up. give up - if route.SysTableTableSchema == nil { - return defaultRoute() - } } - // we only have table_schema to work with - result, err := route.SysTableTableSchema.Evaluate(env) - if err != nil { - return nil, err + // it was not a routed table, and we dont have a schema name to look up. give up + if specifiedKS == "" { + return defaultRoute() } - specifiedKS := result.Value().ToString() + + // we only have table_schema to work with destinations, _, err := vcursor.ResolveDestinations(specifiedKS, nil, []key.Destination{key.DestinationAnyShard{}}) if err != nil { log.Errorf("failed to route information_schema query to keyspace [%s]", specifiedKS) bindVars[sqltypes.BvSchemaName] = sqltypes.StringBindVariable(specifiedKS) return defaultRoute() } - bindVars[sqltypes.BvReplaceSchemaName] = sqltypes.Int64BindVariable(1) + setReplaceSchemaName(bindVars) return destinations, nil } -func (route *Route) paramsRoutedTable(vcursor VCursor, env evalengine.ExpressionEnv, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, error) { - val, err := route.SysTableTableName.Evaluate(env) - if err != nil { - return nil, err - } - tableName := val.Value().ToString() - - var tableSchema string - if route.SysTableTableSchema != nil { - val, err := route.SysTableTableSchema.Evaluate(env) - if err != nil { - return nil, err - } - tableSchema = val.Value().ToString() - } - +func (route *Route) paramsRoutedTable(vcursor VCursor, bindVars map[string]*querypb.BindVariable, tableSchema string, tableName string) ([]*srvtopo.ResolvedShard, error) { tbl := sqlparser.TableName{ Name: sqlparser.NewTableIdent(tableName), Qualifier: sqlparser.NewTableIdent(tableSchema), @@ -478,7 +484,7 @@ func (route *Route) paramsRoutedTable(vcursor VCursor, env evalengine.Expression shards, _, err := vcursor.ResolveDestinations(destination.Keyspace.Name, nil, []key.Destination{key.DestinationAnyShard{}}) bindVars[BvTableName] = sqltypes.StringBindVariable(destination.Name.String()) if tableSchema != "" { - bindVars[sqltypes.BvReplaceSchemaName] = sqltypes.Int64BindVariable(1) + setReplaceSchemaName(bindVars) } return shards, err } @@ -488,6 +494,11 @@ func (route *Route) paramsRoutedTable(vcursor VCursor, env evalengine.Expression return nil, nil } +func setReplaceSchemaName(bindVars map[string]*querypb.BindVariable) { + delete(bindVars, sqltypes.BvSchemaName) + bindVars[sqltypes.BvReplaceSchemaName] = sqltypes.Int64BindVariable(1) +} + func (route *Route) paramsAnyShard(vcursor VCursor, bindVars map[string]*querypb.BindVariable) ([]*srvtopo.ResolvedShard, []map[string]*querypb.BindVariable, error) { rss, _, err := vcursor.ResolveDestinations(route.Keyspace.Name, nil, []key.Destination{key.DestinationAnyShard{}}) if err != nil { diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 50eab386464..7ea60e1ac2f 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -18,7 +18,6 @@ package vtgate import ( "fmt" - "reflect" "runtime" "strings" "testing" @@ -56,30 +55,35 @@ func TestSelectNext(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{"n": sqltypes.Int64BindVariable(2)}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries:\n%v, want\n%v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestSelectDBA(t *testing.T) { executor, sbc1, _, _ := createLegacyExecutorEnv() query := "select * from INFORMATION_SCHEMA.foo" - _, err := executor.Execute( - context.Background(), - "TestSelectDBA", + _, err := executor.Execute(context.Background(), "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), - query, - map[string]*querypb.BindVariable{}, + query, map[string]*querypb.BindVariable{}, ) require.NoError(t, err) - wantQueries := []*querypb.BoundQuery{{ - Sql: query, - BindVariables: map[string]*querypb.BindVariable{}, - }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + wantQueries := []*querypb.BoundQuery{{Sql: query, BindVariables: map[string]*querypb.BindVariable{}}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + sbc1.Queries = nil + + query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", + BindVariables: map[string]*querypb.BindVariable{ + "__vtschemaname": sqltypes.StringBindVariable("performance_schema"), + "__vttablename": sqltypes.StringBindVariable("foo"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + } func TestUnsharded(t *testing.T) { @@ -91,9 +95,7 @@ func TestUnsharded(t *testing.T) { Sql: "select id from music_user_map where id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestUnshardedComments(t *testing.T) { @@ -105,9 +107,7 @@ func TestUnshardedComments(t *testing.T) { Sql: "/* leading */ select id from music_user_map where id = 1 /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) _, err = executorExec(executor, "update music_user_map set id = 1 /* trailing */", nil) require.NoError(t, err) @@ -118,9 +118,7 @@ func TestUnshardedComments(t *testing.T) { Sql: "update music_user_map set id = 1 /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) sbclookup.Queries = nil _, err = executorExec(executor, "delete from music_user_map /* trailing */", nil) @@ -129,9 +127,7 @@ func TestUnshardedComments(t *testing.T) { Sql: "delete from music_user_map /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) sbclookup.Queries = nil _, err = executorExec(executor, "insert into music_user_map values (1) /* trailing */", nil) @@ -140,9 +136,7 @@ func TestUnshardedComments(t *testing.T) { Sql: "insert into music_user_map values (1) /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestStreamUnsharded(t *testing.T) { @@ -216,12 +210,7 @@ func TestStreamBuffering(t *testing.T) { for r := range results { gotResults = append(gotResults, r) } - if !reflect.DeepEqual(gotResults, wantResults) { - t.Logf("len: %d", len(gotResults)) - for i := range gotResults { - t.Errorf("Buffered streaming:\n%v, want\n%v", gotResults[i], wantResults[i]) - } - } + utils.MustMatch(t, wantResults, gotResults) } func TestStreamLimitOffset(t *testing.T) { @@ -681,9 +670,7 @@ func TestSelectEqual(t *testing.T) { Sql: "select id from user where id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -695,9 +682,7 @@ func TestSelectEqual(t *testing.T) { Sql: "select id from user where id = 3", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) if execCount := sbc1.ExecCount.Get(); execCount != 1 { t.Errorf("sbc1.ExecCount: %v, want 1\n", execCount) } @@ -712,9 +697,7 @@ func TestSelectEqual(t *testing.T) { Sql: "select id from user where id = '3'", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) if execCount := sbc1.ExecCount.Get(); execCount != 1 { t.Errorf("sbc1.ExecCount: %v, want 1\n", execCount) } @@ -733,9 +716,7 @@ func TestSelectEqual(t *testing.T) { Sql: "select id from user where `name` = 'foo'", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("foo")}) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ @@ -744,9 +725,7 @@ func TestSelectEqual(t *testing.T) { "name": vars, }, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestSelectDual(t *testing.T) { @@ -758,15 +737,11 @@ func TestSelectDual(t *testing.T) { Sql: "select @@aa.bb from dual", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) _, err = executorExec(executor, "select @@aa.bb from TestUnsharded.dual", nil) require.NoError(t, err) - if !reflect.DeepEqual(lookup.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, lookup.Queries) } func TestSelectComments(t *testing.T) { @@ -778,9 +753,7 @@ func TestSelectComments(t *testing.T) { Sql: "/* leading */ select id from user where id = 1 /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -799,9 +772,7 @@ func TestSelectNormalize(t *testing.T) { "vtg1": sqltypes.TestBindVariable(int64(1)), }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -832,9 +803,7 @@ func TestSelectCaseSensitivity(t *testing.T) { Sql: "select Id from user where iD = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -862,9 +831,7 @@ func TestSelectKeyRange(t *testing.T) { Sql: "select krcol_unique, krcol from keyrange_table where krcol = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -880,9 +847,7 @@ func TestSelectKeyRangeUnique(t *testing.T) { Sql: "select krcol_unique, krcol from keyrange_table where krcol_unique = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -901,9 +866,7 @@ func TestSelectIN(t *testing.T) { "__vals": sqltypes.TestBindVariable([]interface{}{int64(1)}), }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } @@ -920,18 +883,14 @@ func TestSelectIN(t *testing.T) { "__vals": sqltypes.TestBindVariable([]interface{}{int64(1)}), }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantQueries = []*querypb.BoundQuery{{ Sql: "select id from user where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ "__vals": sqltypes.TestBindVariable([]interface{}{int64(3)}), }, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) // In is a bind variable list, that will end up on two shards. // This is using an []interface{} for the bind variable list. @@ -948,9 +907,7 @@ func TestSelectIN(t *testing.T) { "vals": sqltypes.TestBindVariable([]interface{}{int64(1), int64(3)}), }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantQueries = []*querypb.BoundQuery{{ Sql: "select id from user where id in ::__vals", BindVariables: map[string]*querypb.BindVariable{ @@ -958,9 +915,7 @@ func TestSelectIN(t *testing.T) { "vals": sqltypes.TestBindVariable([]interface{}{int64(1), int64(3)}), }, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) // Convert a non-list bind variable. sbc1.Queries = nil @@ -975,9 +930,7 @@ func TestSelectIN(t *testing.T) { Sql: "select id from user where `name` = 'foo'", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) vars, err := sqltypes.BuildBindVariable([]interface{}{sqltypes.NewVarBinary("foo")}) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ @@ -986,9 +939,7 @@ func TestSelectIN(t *testing.T) { "name": vars, }, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestStreamSelectIN(t *testing.T) { @@ -1033,9 +984,7 @@ func TestStreamSelectIN(t *testing.T) { "name": vars, }, }} - if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { - t.Errorf("sbclookup.Queries: %+v, want %+v\n", sbclookup.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbclookup.Queries) } func TestSelectScatter(t *testing.T) { @@ -1064,9 +1013,7 @@ func TestSelectScatter(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } testQueryLog(t, logChan, "TestExecute", "SELECT", wantQueries[0].Sql, 8) } @@ -1209,9 +1156,7 @@ func TestSelectScatterOrderBy(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1232,9 +1177,7 @@ func TestSelectScatterOrderBy(t *testing.T) { wantResult.Rows = append(wantResult.Rows, row) } } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } // TestSelectScatterOrderByVarChar will run an ORDER BY query that will scatter out to 8 shards and return the 8 rows (one per shard) sorted. @@ -1280,9 +1223,7 @@ func TestSelectScatterOrderByVarChar(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1303,9 +1244,7 @@ func TestSelectScatterOrderByVarChar(t *testing.T) { wantResult.Rows = append(wantResult.Rows, row) } } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } func TestStreamSelectScatterOrderBy(t *testing.T) { @@ -1346,9 +1285,7 @@ func TestStreamSelectScatterOrderBy(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1364,9 +1301,7 @@ func TestStreamSelectScatterOrderBy(t *testing.T) { } wantResult.Rows = append(wantResult.Rows, row, row) } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } func TestStreamSelectScatterOrderByVarChar(t *testing.T) { @@ -1408,9 +1343,7 @@ func TestStreamSelectScatterOrderByVarChar(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1426,9 +1359,7 @@ func TestStreamSelectScatterOrderByVarChar(t *testing.T) { } wantResult.Rows = append(wantResult.Rows, row, row) } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } // TestSelectScatterAggregate will run an aggregate query that will scatter out to 8 shards and return 4 aggregated rows. @@ -1470,9 +1401,7 @@ func TestSelectScatterAggregate(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1490,9 +1419,7 @@ func TestSelectScatterAggregate(t *testing.T) { } wantResult.Rows = append(wantResult.Rows, row) } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } func TestStreamSelectScatterAggregate(t *testing.T) { @@ -1533,9 +1460,7 @@ func TestStreamSelectScatterAggregate(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("conn.Queries = %#v, want %#v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1551,9 +1476,7 @@ func TestStreamSelectScatterAggregate(t *testing.T) { } wantResult.Rows = append(wantResult.Rows, row) } - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } // TestSelectScatterLimit will run a limit query (ordered for consistency) against @@ -1596,9 +1519,7 @@ func TestSelectScatterLimit(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{"__upper_limit": sqltypes.Int64BindVariable(3)}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("got: conn.Queries = %v, want: %v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1623,9 +1544,7 @@ func TestSelectScatterLimit(t *testing.T) { sqltypes.NewInt32(2), }) - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } // TestStreamSelectScatterLimit will run a streaming limit query (ordered for consistency) against @@ -1668,9 +1587,7 @@ func TestStreamSelectScatterLimit(t *testing.T) { BindVariables: map[string]*querypb.BindVariable{"__upper_limit": sqltypes.Int64BindVariable(3)}, }} for _, conn := range conns { - if !reflect.DeepEqual(conn.Queries, wantQueries) { - t.Errorf("got: conn.Queries = %v, want: %v", conn.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, conn.Queries) } wantResult := &sqltypes.Result{ @@ -1693,9 +1610,7 @@ func TestStreamSelectScatterLimit(t *testing.T) { sqltypes.NewInt32(2), }) - if !reflect.DeepEqual(gotResult, wantResult) { - t.Errorf("scatter order by:\n%v, want\n%v", gotResult, wantResult) - } + utils.MustMatch(t, wantResult, gotResult) } // TODO(sougou): stream and non-stream testing are very similar. @@ -1712,16 +1627,12 @@ func TestSimpleJoin(t *testing.T) { Sql: "select u1.id from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantQueries = []*querypb.BoundQuery{{ Sql: "select u2.id from user as u2 where u2.id = 3", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ sandboxconn.SingleRowResult.Fields[0], @@ -1754,16 +1665,12 @@ func TestJoinComments(t *testing.T) { Sql: "select u1.id from user as u1 where u1.id = 1 /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantQueries = []*querypb.BoundQuery{{ Sql: "select u2.id from user as u2 where u2.id = 3 /* trailing */", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) testQueryLog(t, logChan, "TestExecute", "SELECT", sql, 2) } @@ -1780,16 +1687,12 @@ func TestSimpleJoinStream(t *testing.T) { Sql: "select u1.id from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantQueries = []*querypb.BoundQuery{{ Sql: "select u2.id from user as u2 where u2.id = 3", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc2.Queries, wantQueries) { - t.Errorf("sbc2.Queries: %+v, want %+v\n", sbc2.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc2.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ sandboxconn.SingleRowResult.Fields[0], @@ -1835,9 +1738,7 @@ func TestVarJoin(t *testing.T) { Sql: "select u1.id, u1.col from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) // We have to use string representation because bindvars type is too complex. got := fmt.Sprintf("%+v", sbc2.Queries) want := `[sql:"select u2.id from user as u2 where u2.id = :u1_col" bind_variables: > ]` @@ -1873,9 +1774,7 @@ func TestVarJoinStream(t *testing.T) { Sql: "select u1.id, u1.col from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) // We have to use string representation because bindvars type is too complex. got := fmt.Sprintf("%+v", sbc2.Queries) want := `[sql:"select u2.id from user as u2 where u2.id = :u1_col" bind_variables: > ]` @@ -1998,9 +1897,7 @@ func TestEmptyJoin(t *testing.T) { "u1_col": sqltypes.NullBindVariable, }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries:\n%v, want\n%v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "id", Type: sqltypes.Int32}, @@ -2036,9 +1933,7 @@ func TestEmptyJoinStream(t *testing.T) { "u1_col": sqltypes.NullBindVariable, }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "id", Type: sqltypes.Int32}, @@ -2081,9 +1976,7 @@ func TestEmptyJoinRecursive(t *testing.T) { "u2_col": sqltypes.NullBindVariable, }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries:\n%+v, want\n%+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "id", Type: sqltypes.Int32}, @@ -2127,9 +2020,7 @@ func TestEmptyJoinRecursiveStream(t *testing.T) { "u2_col": sqltypes.NullBindVariable, }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "id", Type: sqltypes.Int32}, @@ -2163,9 +2054,7 @@ func TestCrossShardSubquery(t *testing.T) { Sql: "select u1.id as id1, u1.col from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) // We have to use string representation because bindvars type is too complex. got := fmt.Sprintf("%+v", sbc2.Queries) want := `[sql:"select u2.id from user as u2 where u2.id = :u1_col" bind_variables: > ]` @@ -2208,9 +2097,7 @@ func TestCrossShardSubqueryStream(t *testing.T) { Sql: "select u1.id as id1, u1.col from user as u1 where u1.id = 1", BindVariables: map[string]*querypb.BindVariable{}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries:\n%+v, want\n%+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) // We have to use string representation because bindvars type is too complex. got := fmt.Sprintf("%+v", sbc2.Queries) want := `[sql:"select u2.id from user as u2 where u2.id = :u1_col" bind_variables: > ]` @@ -2256,9 +2143,7 @@ func TestCrossShardSubqueryGetFields(t *testing.T) { "u1_col": sqltypes.NullBindVariable, }, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries:\n%+v, want\n%+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ @@ -2286,9 +2171,7 @@ func TestSelectBindvarswithPrepare(t *testing.T) { Sql: "select id from user where 1 != 1", BindVariables: map[string]*querypb.BindVariable{"id": sqltypes.Int64BindVariable(1)}, }} - if !reflect.DeepEqual(sbc1.Queries, wantQueries) { - t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) - } + utils.MustMatch(t, wantQueries, sbc1.Queries) if sbc2.Queries != nil { t.Errorf("sbc2.Queries: %+v, want nil\n", sbc2.Queries) } diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index 441085535ad..e918b9d902f 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -2447,3 +2447,21 @@ } } +# system schema in where clause of information_schema query +"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" +{ + "QueryType": "SELECT", + "Original": "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", + "SysTableTableName": "VARBINARY(\"foo\")", + "SysTableTableSchema": "VARBINARY(\"performance_schema\")" + } +} From faeef9724158ea0708ba590bb8f1b02907abcb0b Mon Sep 17 00:00:00 2001 From: GuptaManan100 Date: Tue, 13 Apr 2021 11:33:56 +0530 Subject: [PATCH 41/49] Routing of Information Schema Queries Backport of #7841 * made sysTableTableSchema a slice and fixed merging for SelectDBA queries * updated tests * added tests * changed error message Signed-off-by: GuptaManan100 Signed-off-by: Andres Taylor --- go/test/endtoend/vtgate/system_schema_test.go | 26 ++++ go/vt/vtgate/engine/route.go | 60 ++++++-- go/vt/vtgate/engine/route_test.go | 48 ++++-- go/vt/vtgate/evalengine/expressions.go | 12 -- go/vt/vtgate/executor_select_test.go | 2 +- go/vt/vtgate/planbuilder/route.go | 10 +- go/vt/vtgate/planbuilder/system_tables.go | 12 +- .../planbuilder/testdata/filter_cases.txt | 24 ++- .../planbuilder/testdata/from_cases.txt | 142 ++++++------------ .../planbuilder/testdata/select_cases.txt | 94 ++++++++++++ .../testdata/unsupported_cases.txt | 17 ++- 11 files changed, 279 insertions(+), 168 deletions(-) diff --git a/go/test/endtoend/vtgate/system_schema_test.go b/go/test/endtoend/vtgate/system_schema_test.go index 5954ee5af76..71bb809142f 100644 --- a/go/test/endtoend/vtgate/system_schema_test.go +++ b/go/test/endtoend/vtgate/system_schema_test.go @@ -187,3 +187,29 @@ func TestSystemSchemaQueryWithoutQualifier(t *testing.T) { qr3 := exec(t, conn2, queryWithoutQualifier) require.Equal(t, qr2, qr3) } + +func TestMultipleSchemaPredicates(t *testing.T) { + defer cluster.PanicHandler(t) + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + query := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from information_schema.tables t "+ + "join information_schema.columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, KeyspaceName, KeyspaceName) + qr1 := exec(t, conn, query) + require.EqualValues(t, 4, len(qr1.Fields)) + + // test a query with two keyspace names + query = fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+ + "from information_schema.tables t "+ + "join information_schema.columns c "+ + "on c.table_schema = t.table_schema and c.table_name = t.table_name "+ + "where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, "a") + _, err = conn.ExecuteFetch(query, 1000, true) + require.Error(t, err) + require.Contains(t, err.Error(), "specifying two different database in the query is not supported") +} diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 61407b556f2..362bbd15c25 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -94,8 +94,8 @@ type Route struct { ScatterErrorsAsWarnings bool // The following two fields are used when routing information_schema queries - SysTableTableSchema evalengine.Expr - SysTableTableName evalengine.Expr + SysTableTableSchema []evalengine.Expr + SysTableTableName []evalengine.Expr // Route does not take inputs noInputs @@ -408,7 +408,7 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q return destinations, vterrors.Wrapf(err, "failed to find information about keyspace `%s`", ks) } - if route.SysTableTableName == nil && route.SysTableTableSchema == nil { + if len(route.SysTableTableName) == 0 && len(route.SysTableTableSchema) == 0 { return defaultRoute() } @@ -418,22 +418,38 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q } var specifiedKS string - if route.SysTableTableSchema != nil { - result, err := route.SysTableTableSchema.Evaluate(env) + for _, tableSchema := range route.SysTableTableSchema { + result, err := tableSchema.Evaluate(env) if err != nil { return nil, err } - specifiedKS = result.Value().ToString() + ks := result.Value().ToString() + if specifiedKS == "" { + specifiedKS = ks + } + if specifiedKS != ks { + return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "specifying two different database in the query is not supported") + } + } + if specifiedKS != "" { bindVars[sqltypes.BvSchemaName] = sqltypes.StringBindVariable(specifiedKS) } var tableName string - if route.SysTableTableName != nil { - val, err := route.SysTableTableName.Evaluate(env) + for _, sysTableName := range route.SysTableTableName { + val, err := sysTableName.Evaluate(env) if err != nil { return nil, err } - tableName = val.Value().ToString() + tabName := val.Value().ToString() + if tableName == "" { + tableName = tabName + } + if tableName != tabName { + return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "two predicates for table_name not supported") + } + } + if tableName != "" { bindVars[BvTableName] = sqltypes.StringBindVariable(tableName) } @@ -723,11 +739,27 @@ func (route *Route) description() PrimitiveDescription { if len(route.Values) > 0 { other["Values"] = route.Values } - if route.SysTableTableSchema != nil { - other["SysTableTableSchema"] = route.SysTableTableSchema.String() - } - if route.SysTableTableName != nil { - other["SysTableTableName"] = route.SysTableTableName.String() + if len(route.SysTableTableSchema) != 0 { + sysTabSchema := "[" + for idx, tableSchema := range route.SysTableTableSchema { + if idx != 0 { + sysTabSchema += ", " + } + sysTabSchema += tableSchema.String() + } + sysTabSchema += "]" + other["SysTableTableSchema"] = sysTabSchema + } + if len(route.SysTableTableName) != 0 { + sysTableName := "[" + for idx, tableName := range route.SysTableTableName { + if idx != 0 { + sysTableName += ", " + } + sysTableName += tableName.String() + } + sysTableName += "]" + other["SysTableTableName"] = sysTableName } orderBy := GenericJoin(route.OrderBy, orderByToString) if orderBy != "" { diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go index bb8bad02339..93deb22a727 100644 --- a/go/vt/vtgate/engine/route_test.go +++ b/go/vt/vtgate/engine/route_test.go @@ -78,23 +78,24 @@ func TestSelectUnsharded(t *testing.T) { } func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) { - stringToExpr := func(in string) evalengine.Expr { - var schema evalengine.Expr - if in != "" { - schema = evalengine.NewLiteralString([]byte(in)) + stringListToExprList := func(in []string) []evalengine.Expr { + var schema []evalengine.Expr + for _, s := range in { + schema = append(schema, evalengine.NewLiteralString([]byte(s))) } return schema } type testCase struct { - tableSchema, tableName, testName string - expectedLog []string - routed bool + tableSchema, tableName []string + testName string + expectedLog []string + routed bool } tests := []testCase{{ testName: "both schema and table predicates - routed table", - tableSchema: "schema", - tableName: "table", + tableSchema: []string{"schema"}, + tableName: []string{"table"}, routed: true, expectedLog: []string{ "FindTable(`schema`.`table`)", @@ -102,8 +103,17 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) "ExecuteMultiShard routedKeyspace.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"routedTable\" } false false"}, }, { testName: "both schema and table predicates - not routed", - tableSchema: "schema", - tableName: "table", + tableSchema: []string{"schema"}, + tableName: []string{"table"}, + routed: false, + expectedLog: []string{ + "FindTable(`schema`.`table`)", + "ResolveDestinations schema [] Destinations:DestinationAnyShard()", + "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"table\" } false false"}, + }, { + testName: "multiple schema and table predicates", + tableSchema: []string{"schema", "schema", "schema"}, + tableName: []string{"table", "table", "table"}, routed: false, expectedLog: []string{ "FindTable(`schema`.`table`)", @@ -111,7 +121,7 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) "ExecuteMultiShard schema.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" __vttablename: type:VARBINARY value:\"table\" } false false"}, }, { testName: "table name predicate - routed table", - tableName: "tableName", + tableName: []string{"tableName"}, routed: true, expectedLog: []string{ "FindTable(tableName)", @@ -119,7 +129,7 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) "ExecuteMultiShard routedKeyspace.1: dummy_select {__vttablename: type:VARBINARY value:\"routedTable\" } false false"}, }, { testName: "table name predicate - not routed", - tableName: "tableName", + tableName: []string{"tableName"}, routed: false, expectedLog: []string{ "FindTable(tableName)", @@ -127,7 +137,13 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) "ExecuteMultiShard ks.1: dummy_select {__vttablename: type:VARBINARY value:\"tableName\" } false false"}, }, { testName: "schema predicate", - tableSchema: "myKeyspace", + tableSchema: []string{"myKeyspace"}, + expectedLog: []string{ + "ResolveDestinations myKeyspace [] Destinations:DestinationAnyShard()", + "ExecuteMultiShard myKeyspace.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" } false false"}, + }, { + testName: "multiple schema predicates", + tableSchema: []string{"myKeyspace", "myKeyspace", "myKeyspace", "myKeyspace"}, expectedLog: []string{ "ResolveDestinations myKeyspace [] Destinations:DestinationAnyShard()", "ExecuteMultiShard myKeyspace.1: dummy_select {__replacevtschemaname: type:INT64 value:\"1\" } false false"}, @@ -148,8 +164,8 @@ func TestSelectInformationSchemaWithTableAndSchemaWithRoutedTables(t *testing.T) }, Query: "dummy_select", FieldQuery: "dummy_select_field", - SysTableTableSchema: stringToExpr(tc.tableSchema), - SysTableTableName: stringToExpr(tc.tableName), + SysTableTableSchema: stringListToExprList(tc.tableSchema), + SysTableTableName: stringListToExprList(tc.tableName), } vc := &loggingVCursor{ shards: []string{"1"}, diff --git a/go/vt/vtgate/evalengine/expressions.go b/go/vt/vtgate/evalengine/expressions.go index baafbe8a0c2..a32badee480 100644 --- a/go/vt/vtgate/evalengine/expressions.go +++ b/go/vt/vtgate/evalengine/expressions.go @@ -327,15 +327,3 @@ func evaluateByType(val *querypb.BindVariable) (EvalResult, error) { func (e *EvalResult) debugString() string { return fmt.Sprintf("(%s) %d %d %f %s", querypb.Type_name[int32(e.typ)], e.ival, e.uval, e.fval, string(e.bytes)) } - -// AreExprEqual checks if the provided Expr are the same or not -func AreExprEqual(expr1 Expr, expr2 Expr) bool { - // Check the types of the two expressions, if they don't match then the two are not equal - if fmt.Sprintf("%T", expr1) != fmt.Sprintf("%T", expr2) { - return false - } - if expr1.String() == expr2.String() { - return true - } - return false -} diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 7ea60e1ac2f..2eb31930b34 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -2290,7 +2290,7 @@ func TestSelectFromInformationSchema(t *testing.T) { // check failure when trying to query two keyspaces _, err := exec(executor, session, "SELECT B.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES AS A, INFORMATION_SCHEMA.COLUMNS AS B WHERE A.TABLE_SCHEMA = 'TestExecutor' AND A.TABLE_SCHEMA = 'TestXBadSharding'") require.Error(t, err) - require.Contains(t, err.Error(), "two predicates for specifying the database are not supported") + require.Contains(t, err.Error(), "specifying two different database in the query is not supported") // we pick a keyspace and query for table_schema = database(). should be routed to the picked keyspace session.TargetString = "TestExecutor" diff --git a/go/vt/vtgate/planbuilder/route.go b/go/vt/vtgate/planbuilder/route.go index ea6baaa24c7..5e921e0abec 100644 --- a/go/vt/vtgate/planbuilder/route.go +++ b/go/vt/vtgate/planbuilder/route.go @@ -392,15 +392,7 @@ func (rb *route) JoinCanMerge(pb *primitiveBuilder, rrb *route, ajoin *sqlparser if where == nil { return true } - hasRuntimeRoutingPredicates := false - sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { - col, ok := node.(*sqlparser.ColName) - if ok { - hasRuntimeRoutingPredicates = hasRuntimeRoutingPredicates || isTableNameCol(col) || isDbNameCol(col) - } - return !hasRuntimeRoutingPredicates, nil - }, where) - return !hasRuntimeRoutingPredicates + return ajoin != nil } if ajoin == nil { return false diff --git a/go/vt/vtgate/planbuilder/system_tables.go b/go/vt/vtgate/planbuilder/system_tables.go index 84ee0d323d7..3d073d63a65 100644 --- a/go/vt/vtgate/planbuilder/system_tables.go +++ b/go/vt/vtgate/planbuilder/system_tables.go @@ -18,9 +18,7 @@ package planbuilder import ( "vitess.io/vitess/go/sqltypes" - vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/vterrors" "vitess.io/vitess/go/vt/vtgate/engine" "vitess.io/vitess/go/vt/vtgate/evalengine" ) @@ -36,15 +34,9 @@ func (pb *primitiveBuilder) findSysInfoRoutingPredicates(expr sqlparser.Expr, ru } if isTableSchema { - if rut.eroute.SysTableTableSchema != nil && !evalengine.AreExprEqual(rut.eroute.SysTableTableSchema, out) { - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "two predicates for specifying the database are not supported") - } - rut.eroute.SysTableTableSchema = out + rut.eroute.SysTableTableSchema = append(rut.eroute.SysTableTableSchema, out) } else { - if rut.eroute.SysTableTableName != nil && !evalengine.AreExprEqual(rut.eroute.SysTableTableName, out) { - return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "two predicates for table_name not supported") - } - rut.eroute.SysTableTableName = out + rut.eroute.SysTableTableName = append(rut.eroute.SysTableTableName, out) } return nil diff --git a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt index a2ba4862a31..308c97f6afb 100644 --- a/go/vt/vtgate/planbuilder/testdata/filter_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/filter_cases.txt @@ -1683,7 +1683,21 @@ # query trying to query two different keyspaces at the same time "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'" -"two predicates for specifying the database are not supported" +{ + "QueryType": "SELECT", + "Original": "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'user' AND TABLE_SCHEMA = 'main'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", + "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_SCHEMA = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"user\"), VARBINARY(\"main\")]" + } +} # information_schema query using database() func "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = database()" @@ -1716,7 +1730,7 @@ }, "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname", - "SysTableTableSchema": "VARBINARY(\"ks\")" + "SysTableTableSchema": "[VARBINARY(\"ks\")]" } } @@ -1751,8 +1765,8 @@ }, "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and TABLE_NAME = :__vttablename", - "SysTableTableName": "VARBINARY(\"route1\")", - "SysTableTableSchema": "VARBINARY(\"ks\")" + "SysTableTableName": "[VARBINARY(\"route1\")]", + "SysTableTableSchema": "[VARBINARY(\"ks\")]" } } @@ -1770,7 +1784,7 @@ }, "FieldQuery": "select * from INFORMATION_SCHEMA.`TABLES` where 1 != 1", "Query": "select * from INFORMATION_SCHEMA.`TABLES` where TABLE_SCHEMA = :__vtschemaname and other_column = 42", - "SysTableTableSchema": "VARBINARY(\"ks\")" + "SysTableTableSchema": "[VARBINARY(\"ks\")]" } } diff --git a/go/vt/vtgate/planbuilder/testdata/from_cases.txt b/go/vt/vtgate/planbuilder/testdata/from_cases.txt index e918b9d902f..a50a63fcee0 100644 --- a/go/vt/vtgate/planbuilder/testdata/from_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/from_cases.txt @@ -2192,34 +2192,15 @@ "QueryType": "SELECT", "Original": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = ':vtg1' and rc.constraint_schema = database() and rc.table_name = ':vtg1'", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "1,2,3,4,-1,-2", - "TableName": "_", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select rc.update_rule as on_update, rc.delete_rule as on_delete, rc.constraint_schema, rc.constraint_name from information_schema.referential_constraints as rc where 1 != 1", - "Query": "select rc.update_rule as on_update, rc.delete_rule as on_delete, rc.constraint_schema, rc.constraint_name from information_schema.referential_constraints as rc where rc.constraint_schema = database() and rc.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\":vtg1\")" - }, - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name` from information_schema.key_column_usage as fk where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name` from information_schema.key_column_usage as fk where fk.constraint_schema = :rc_constraint_schema and fk.constraint_name = :rc_constraint_name and fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\":vtg1\")" - } - ] + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = :__vttablename and rc.constraint_schema = database() and rc.table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\":vtg1\"), VARBINARY(\":vtg1\")]" } } @@ -2237,7 +2218,7 @@ }, "FieldQuery": "select * from information_schema.schemata where 1 != 1", "Query": "select * from information_schema.schemata where schema_name = :__vtschemaname", - "SysTableTableSchema": "VARBINARY(\"user\")" + "SysTableTableSchema": "[VARBINARY(\"user\")]" } } @@ -2255,8 +2236,8 @@ }, "FieldQuery": "select table_comment from information_schema.`tables` where 1 != 1", "Query": "select table_comment from information_schema.`tables` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"schema_name\")" + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"schema_name\")]" } } @@ -2266,36 +2247,16 @@ "QueryType": "SELECT", "Original": "SELECT fk.referenced_table_name AS 'to_table', fk.referenced_column_name AS 'primary_key',fk.column_name AS 'column',fk.constraint_name AS 'name',rc.update_rule AS 'on_update',rc.delete_rule AS 'on_delete' FROM information_schema.referential_constraints rc JOIN information_schema.key_column_usage fk USING (constraint_schema, constraint_name) WHERE fk.referenced_column_name IS NOT NULL AND fk.table_schema = 'table_schema' AND fk.table_name = 'table_name' AND rc.constraint_schema = 'table_schema' AND rc.table_name = 'table_name'", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "1,2,3,4,-1,-2", - "TableName": "_", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select rc.update_rule as on_update, rc.delete_rule as on_delete, rc.constraint_schema, rc.constraint_name from information_schema.referential_constraints as rc where 1 != 1", - "Query": "select rc.update_rule as on_update, rc.delete_rule as on_delete, rc.constraint_schema, rc.constraint_name from information_schema.referential_constraints as rc where rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" - }, - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name` from information_schema.key_column_usage as fk where 1 != 1", - "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name` from information_schema.key_column_usage as fk where fk.constraint_schema = :rc_constraint_schema and fk.constraint_name = :rc_constraint_name and fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" - } - ] + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where 1 != 1", + "Query": "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as `name`, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk on rc.constraint_schema = fk.constraint_schema and rc.constraint_name = fk.constraint_name where fk.referenced_column_name is not null and fk.table_schema = :__vtschemaname and fk.table_name = :__vttablename and rc.constraint_schema = :__vtschemaname and rc.table_name = :__vttablename", + "SysTableTableName": "[VARBINARY(\"table_name\"), VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"table_schema\")]" } } @@ -2305,35 +2266,16 @@ "QueryType": "SELECT", "Original": "SELECT cc.constraint_name AS 'name', cc.check_clause AS 'expression' FROM information_schema.check_constraints cc JOIN information_schema.table_constraints tc USING (constraint_schema, constraint_name) WHERE tc.table_schema = 'table_schema' AND tc.table_name = 'table_name' AND cc.constraint_schema = 'constraint_schema'", "Instructions": { - "OperatorType": "Join", - "Variant": "Join", - "JoinColumnIndexes": "-1,-2", - "TableName": "_", - "Inputs": [ - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression, cc.constraint_schema from information_schema.check_constraints as cc where 1 != 1", - "Query": "select cc.constraint_name as `name`, cc.check_clause as expression, cc.constraint_schema from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname", - "SysTableTableSchema": "VARBINARY(\"constraint_schema\")" - }, - { - "OperatorType": "Route", - "Variant": "SelectDBA", - "Keyspace": { - "Name": "main", - "Sharded": false - }, - "FieldQuery": "select 1 from information_schema.table_constraints as tc where 1 != 1", - "Query": "select 1 from information_schema.table_constraints as tc where tc.constraint_schema = :cc_constraint_schema and tc.constraint_name = :cc_constraint_name and tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" - } - ] + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where 1 != 1", + "Query": "select cc.constraint_name as `name`, cc.check_clause as expression from information_schema.check_constraints as cc join information_schema.table_constraints as tc on cc.constraint_schema = tc.constraint_schema and cc.constraint_name = tc.constraint_name where tc.table_schema = :__vtschemaname and tc.table_name = :__vttablename and cc.constraint_schema = :__vtschemaname", + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\"), VARBINARY(\"constraint_schema\")]" } } @@ -2351,8 +2293,8 @@ }, "FieldQuery": "select column_name from information_schema.statistics where 1 != 1", "Query": "select column_name from information_schema.statistics where index_name = 'PRIMARY' and table_schema = :__vtschemaname and table_name = :__vttablename order by seq_in_index asc", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]" } } @@ -2370,8 +2312,8 @@ }, "FieldQuery": "select generation_expression from information_schema.`columns` where 1 != 1", "Query": "select generation_expression from information_schema.`columns` where table_schema = :__vtschemaname and table_name = :__vttablename and column_name = 'column_name'", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]" } } @@ -2406,7 +2348,7 @@ }, "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]" } } @@ -2424,8 +2366,8 @@ }, "FieldQuery": "select table_name from (select * from information_schema.`tables` where 1 != 1) as _subquery where 1 != 1", "Query": "select table_name from (select * from information_schema.`tables` where table_schema = :__vtschemaname) as _subquery where _subquery.table_type = 'table_type' and _subquery.table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"table_name\")", - "SysTableTableSchema": "VARBINARY(\"table_schema\")" + "SysTableTableName": "[VARBINARY(\"table_name\")]", + "SysTableTableSchema": "[VARBINARY(\"table_schema\")]" } } @@ -2443,7 +2385,7 @@ }, "FieldQuery": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where 1 != 1", "Query": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname and cc.table_schema = :__vtschemaname", - "SysTableTableSchema": "VARBINARY(\"a\")" + "SysTableTableSchema": "[VARBINARY(\"a\"), VARBINARY(\"a\")]" } } @@ -2461,7 +2403,7 @@ }, "FieldQuery": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where 1 != 1", "Query": "select COUNT(*) from INFORMATION_SCHEMA.`TABLES` where table_schema = :__vtschemaname and table_name = :__vttablename", - "SysTableTableName": "VARBINARY(\"foo\")", - "SysTableTableSchema": "VARBINARY(\"performance_schema\")" + "SysTableTableName": "[VARBINARY(\"foo\")]", + "SysTableTableSchema": "[VARBINARY(\"performance_schema\")]" } } diff --git a/go/vt/vtgate/planbuilder/testdata/select_cases.txt b/go/vt/vtgate/planbuilder/testdata/select_cases.txt index e80cb524aef..b94fd79accd 100644 --- a/go/vt/vtgate/planbuilder/testdata/select_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/select_cases.txt @@ -1661,3 +1661,97 @@ ] } } + +# Select from information schema query with two tables that route should be merged +"SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" +{ + "QueryType": "SELECT", + "Original": "SELECT DELETE_RULE, UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.COLUMN_NAME = 'id' AND KCU.REFERENCED_TABLE_SCHEMA = 'test' AND KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", + "Query": "select DELETE_RULE, UPDATE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.COLUMN_NAME = 'id' and KCU.REFERENCED_TABLE_SCHEMA = 'test' and KCU.CONSTRAINT_NAME = 'data_type_table_id_fkey' order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]" + } +} + +# Select from information schema query with three tables such that route for 2 should be merged but not for the last. +"SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME" +{ + "QueryType": "SELECT", + "Original": "SELECT KCU.DELETE_RULE, S.UPDATE_RULE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS KCU INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS AS RC ON KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME, INFORMATION_SCHEMA.K AS S WHERE KCU.TABLE_SCHEMA = 'test' AND KCU.TABLE_NAME = 'data_type_table' AND KCU.TABLE_NAME = 'data_type_table' AND S.TABLE_SCHEMA = 'test' AND S.TABLE_NAME = 'sc' ORDER BY KCU.CONSTRAINT_NAME, KCU.COLUMN_NAME", + "Instructions": { + "OperatorType": "Join", + "Variant": "Join", + "JoinColumnIndexes": "-1,1", + "TableName": "_", + "Inputs": [ + { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where 1 != 1", + "Query": "select KCU.DELETE_RULE from INFORMATION_SCHEMA.KEY_COLUMN_USAGE as KCU join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS as RC on KCU.CONSTRAINT_NAME = RC.CONSTRAINT_NAME where KCU.TABLE_SCHEMA = :__vtschemaname and KCU.TABLE_NAME = :__vttablename and KCU.TABLE_NAME = :__vttablename order by KCU.CONSTRAINT_NAME asc, KCU.COLUMN_NAME asc", + "SysTableTableName": "[VARBINARY(\"data_type_table\"), VARBINARY(\"data_type_table\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]" + }, + { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where 1 != 1", + "Query": "select S.UPDATE_RULE from INFORMATION_SCHEMA.K as S where S.TABLE_SCHEMA = :__vtschemaname and S.TABLE_NAME = :__vttablename", + "SysTableTableName": "[VARBINARY(\"sc\")]", + "SysTableTableSchema": "[VARBINARY(\"test\")]" + } + ] + } +} + +#information_schema table sizes +"SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?" +{ + "QueryType": "SELECT", + "Original": "SELECT SUM(data_length + index_length) as size FROM information_schema.TABLES WHERE table_schema = ?", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where 1 != 1", + "Query": "select SUM(data_length + index_length) as size from information_schema.`TABLES` where table_schema = :__vtschemaname", + "SysTableTableSchema": "[:v1]" + } +} + +#information_schema referential contraints +"SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position" +{ + "QueryType": "SELECT", + "Original": "SELECT kcu.constraint_name constraint_name, kcu.column_name column_name, kcu.referenced_table_name referenced_table_name, kcu.referenced_column_name referenced_column_name, kcu.ordinal_position ordinal_position, kcu.table_name table_name, rc.delete_rule delete_rule, rc.update_rule update_rule FROM information_schema.key_column_usage AS kcu INNER JOIN information_schema.referential_constraints AS rc ON kcu.constraint_name = rc.constraint_name WHERE kcu.table_schema = ? AND rc.constraint_schema = ? AND kcu.referenced_column_name IS NOT NULL ORDER BY ordinal_position", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where 1 != 1", + "Query": "select kcu.constraint_name as constraint_name, kcu.column_name as column_name, kcu.referenced_table_name as referenced_table_name, kcu.referenced_column_name as referenced_column_name, kcu.ordinal_position as ordinal_position, kcu.table_name as table_name, rc.delete_rule as delete_rule, rc.update_rule as update_rule from information_schema.key_column_usage as kcu join information_schema.referential_constraints as rc on kcu.constraint_name = rc.constraint_name where kcu.table_schema = :__vtschemaname and rc.constraint_schema = :__vtschemaname and kcu.referenced_column_name is not null order by ordinal_position asc", + "SysTableTableSchema": "[:v1, :v2]" + } +} diff --git a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt index 4bb18995a80..99970fe9d1a 100644 --- a/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt +++ b/go/vt/vtgate/planbuilder/testdata/unsupported_cases.txt @@ -379,8 +379,23 @@ "unsupported: this construct is not supported on sharded keyspace" # unsupported two predicates specifying the database for the same table if they are different +# will fail on run time but will pass on the planbuilder "SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'constraint_schema' AND cc.table_schema = 'a'" -"two predicates for specifying the database are not supported" +{ + "QueryType": "SELECT", + "Original": "SELECT cc.constraint_name AS 'name' FROM information_schema.check_constraints cc WHERE cc.constraint_schema = 'constraint_schema' AND cc.table_schema = 'a'", + "Instructions": { + "OperatorType": "Route", + "Variant": "SelectDBA", + "Keyspace": { + "Name": "main", + "Sharded": false + }, + "FieldQuery": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where 1 != 1", + "Query": "select cc.constraint_name as `name` from information_schema.check_constraints as cc where cc.constraint_schema = :__vtschemaname and cc.table_schema = :__vtschemaname", + "SysTableTableSchema": "[VARBINARY(\"constraint_schema\"), VARBINARY(\"a\")]" + } +} # create view with Cannot auto-resolve for cross-shard joins "create view user.view_a as select col from user join user_extra" From d3ff88b07182f4363f58834361716fe33ba23587 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Sun, 9 May 2021 21:44:16 +0530 Subject: [PATCH 42/49] System schema query predicate fix Backport of #8087 This is a combination of 4 commits. * add e2e test for system schema * add unit test for system schema issue * redirect to default route if not able to resolve the keyspace in case of information_schema query * update test with new error message Signed-off-by: Harshit Gangal Signed-off-by: Andres Taylor --- go/test/endtoend/vtgate/system_schema_test.go | 2 + go/vt/vtgate/engine/route.go | 5 +++ go/vt/vtgate/executor_select_test.go | 29 +++++++++++- go/vt/vtgate/vindexes/vschema.go | 7 ++- go/vt/vtgate/vindexes/vschema_test.go | 45 +++++++------------ go/vt/vtgate/vtgate_test.go | 6 +-- 6 files changed, 58 insertions(+), 36 deletions(-) diff --git a/go/test/endtoend/vtgate/system_schema_test.go b/go/test/endtoend/vtgate/system_schema_test.go index 71bb809142f..8e5c29f3b5f 100644 --- a/go/test/endtoend/vtgate/system_schema_test.go +++ b/go/test/endtoend/vtgate/system_schema_test.go @@ -78,6 +78,8 @@ func TestInformationSchemaQuery(t *testing.T) { assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'") assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema") assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'") + assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks' and table_name = 't1'", "vt_ks") + assertSingleRowIsReturned(t, conn, "table_schema = 'ks' and table_name = 't1'", "vt_ks") } func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) { diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 362bbd15c25..598d3e3af47 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -462,6 +462,11 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q if tableName != "" { rss, err := route.paramsRoutedTable(vcursor, bindVars, specifiedKS, tableName) if err != nil { + // Only if keyspace is not found in vschema, we try with default keyspace. + // As the in the table_schema predicates for a keyspace 'ks' it can contain 'vt_ks'. + if vterrors.Code(err) == vtrpcpb.Code_NOT_FOUND { + return defaultRoute() + } return nil, err } if rss != nil { diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index 2eb31930b34..99cb73273f4 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -69,8 +69,8 @@ func TestSelectDBA(t *testing.T) { require.NoError(t, err) wantQueries := []*querypb.BoundQuery{{Sql: query, BindVariables: map[string]*querypb.BindVariable{}}} utils.MustMatch(t, wantQueries, sbc1.Queries) - sbc1.Queries = nil + sbc1.Queries = nil query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'" _, err = executor.Execute(context.Background(), "TestSelectDBA", NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), @@ -84,6 +84,33 @@ func TestSelectDBA(t *testing.T) { }}} utils.MustMatch(t, wantQueries, sbc1.Queries) + sbc1.Queries = nil + query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks' and table_name = 'user'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname and table_name = :__vttablename", + BindVariables: map[string]*querypb.BindVariable{ + "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), + "__vttablename": sqltypes.StringBindVariable("user"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + + sbc1.Queries = nil + query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks'" + _, err = executor.Execute(context.Background(), "TestSelectDBA", + NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}), + query, map[string]*querypb.BindVariable{}, + ) + require.NoError(t, err) + wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname", + BindVariables: map[string]*querypb.BindVariable{ + "__vtschemaname": sqltypes.StringBindVariable("vt_ks"), + }}} + utils.MustMatch(t, wantQueries, sbc1.Queries) + } func TestUnsharded(t *testing.T) { diff --git a/go/vt/vtgate/vindexes/vschema.go b/go/vt/vtgate/vindexes/vschema.go index 3054b611dde..7e5c4d70623 100644 --- a/go/vt/vtgate/vindexes/vschema.go +++ b/go/vt/vtgate/vindexes/vschema.go @@ -23,6 +23,9 @@ import ( "io/ioutil" "sort" + vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" + "vitess.io/vitess/go/vt/vterrors" + "vitess.io/vitess/go/json2" "vitess.io/vitess/go/sqltypes" "vitess.io/vitess/go/vt/sqlparser" @@ -481,7 +484,7 @@ func (vschema *VSchema) findTable(keyspace, tablename string) (*Table, error) { } ks, ok := vschema.Keyspaces[keyspace] if !ok { - return nil, fmt.Errorf("keyspace %s not found in vschema", keyspace) + return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "keyspace %s not found in vschema", keyspace) } table := ks.Tables[tablename] if table == nil { @@ -559,7 +562,7 @@ func (vschema *VSchema) FindVindex(keyspace, name string) (Vindex, error) { } ks, ok := vschema.Keyspaces[keyspace] if !ok { - return nil, fmt.Errorf("keyspace %s not found in vschema", keyspace) + return nil, vterrors.Errorf(vtrpcpb.Code_NOT_FOUND, "keyspace %s not found in vschema", keyspace) } return ks.Vindexes[name], nil } diff --git a/go/vt/vtgate/vindexes/vschema_test.go b/go/vt/vtgate/vindexes/vschema_test.go index 823b46f4e8c..0dc1782d47b 100644 --- a/go/vt/vtgate/vindexes/vschema_test.go +++ b/go/vt/vtgate/vindexes/vschema_test.go @@ -2156,33 +2156,24 @@ func TestFindTable(t *testing.T) { } vschema, _ := BuildVSchema(&input) _, err := vschema.FindTable("", "t1") - wantErr := "ambiguous table reference: t1" - if err == nil || err.Error() != wantErr { - t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr) - } + require.EqualError(t, err, "ambiguous table reference: t1") + _, err = vschema.FindTable("", "none") - wantErr = "table none not found" - if err == nil || err.Error() != wantErr { - t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr) - } - got, err := vschema.FindTable("", "ta") - if err != nil { - t.Error(err) - return - } + require.EqualError(t, err, "table none not found") + ta := &Table{ Name: sqlparser.NewTableIdent("ta"), Keyspace: &Keyspace{ Name: "ksa", }, } - if !reflect.DeepEqual(got, ta) { - t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, ta) - } + got, err := vschema.FindTable("", "ta") + require.NoError(t, err) + require.Equal(t, ta, got) + got, _ = vschema.FindTable("ksa", "ta") - if !reflect.DeepEqual(got, ta) { - t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, ta) - } + require.Equal(t, ta, got) + none := &Table{ Name: sqlparser.NewTableIdent("none"), Keyspace: &Keyspace{ @@ -2190,19 +2181,13 @@ func TestFindTable(t *testing.T) { }, } got, _ = vschema.FindTable("ksa", "none") - if !reflect.DeepEqual(got, none) { - t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, none) - } + require.Equal(t, none, got) + _, err = vschema.FindTable("ksb", "none") - wantErr = "table none not found" - if err == nil || err.Error() != wantErr { - t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr) - } + require.EqualError(t, err, "table none not found") + _, err = vschema.FindTable("none", "aa") - wantErr = "keyspace none not found in vschema" - if err == nil || err.Error() != wantErr { - t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr) - } + require.EqualError(t, err, "keyspace none not found in vschema") } func TestFindTableOrVindex(t *testing.T) { diff --git a/go/vt/vtgate/vtgate_test.go b/go/vt/vtgate/vtgate_test.go index ff465ff4931..01ddb499c0a 100644 --- a/go/vt/vtgate/vtgate_test.go +++ b/go/vt/vtgate/vtgate_test.go @@ -21,6 +21,8 @@ import ( "strings" "testing" + "github.com/stretchr/testify/assert" + "context" "github.com/golang/protobuf/proto" @@ -140,9 +142,7 @@ func TestVTGateExecuteWithKeyspaceShard(t *testing.T) { nil, ) want := "vtgate: : keyspace invalid_keyspace not found in vschema" - if err == nil || err.Error() != want { - t.Errorf("Execute: %v, want %s", err, want) - } + assert.EqualError(t, err, want) // Valid keyspace/shard. _, qr, err = rpcVTGate.Execute( From 7e448aa5515e1788d0fb717c8504d29cb8eed954 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Mon, 10 May 2021 17:09:51 +0530 Subject: [PATCH 43/49] Queryservice fix Backport of #8089 This is a combination of 3 commits. * remove precheck of tablet serving and target * remove the additional logic and return error if queryservice not found to serve query * fix test as per new change Signed-off-by: Harshit Gangal Signed-off-by: Andres Taylor --- go/vt/discovery/fake_healthcheck.go | 7 --- go/vt/discovery/healthcheck.go | 8 --- go/vt/vtgate/legacy_scatter_conn_test.go | 25 ++++---- go/vt/vtgate/scatter_conn.go | 18 +----- go/vt/vtgate/scatter_conn_test.go | 16 +++-- go/vt/vttablet/sandboxconn/sandboxconn.go | 71 ++++++++++++++++++++--- 6 files changed, 89 insertions(+), 56 deletions(-) diff --git a/go/vt/discovery/fake_healthcheck.go b/go/vt/discovery/fake_healthcheck.go index bbb1ec98baa..4407ae50ebc 100644 --- a/go/vt/discovery/fake_healthcheck.go +++ b/go/vt/discovery/fake_healthcheck.go @@ -150,13 +150,6 @@ func (fhc *FakeHealthCheck) TabletConnection(alias *topodatapb.TabletAlias, targ defer fhc.mu.RUnlock() for _, item := range fhc.items { if proto.Equal(alias, item.ts.Tablet.Alias) { - if !item.ts.Serving { - return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.NotServing) - } - if target != nil && !proto.Equal(item.ts.Target, target) { - return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s: target mismatch %v vs %v", vterrors.WrongTablet, item.ts.Target, target) - } - return item.ts.Conn, nil } } diff --git a/go/vt/discovery/healthcheck.go b/go/vt/discovery/healthcheck.go index 90a64a788aa..1a3670d88df 100644 --- a/go/vt/discovery/healthcheck.go +++ b/go/vt/discovery/healthcheck.go @@ -45,8 +45,6 @@ import ( "sync" "time" - "github.com/golang/protobuf/proto" - "vitess.io/vitess/go/flagutil" "vitess.io/vitess/go/stats" "vitess.io/vitess/go/vt/log" @@ -700,12 +698,6 @@ func (hc *HealthCheckImpl) TabletConnection(alias *topodata.TabletAlias, target //TODO: test that throws this error return nil, vterrors.Errorf(vtrpc.Code_NOT_FOUND, "tablet: %v is either down or nonexistent", alias) } - if !thc.Serving { - return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, vterrors.NotServing) - } - if target != nil && !proto.Equal(thc.Target, target) { - return nil, vterrors.Errorf(vtrpc.Code_FAILED_PRECONDITION, "%s: target mismatch %v vs %v", vterrors.WrongTablet, thc.Target, target) - } return thc.Connection(), nil } diff --git a/go/vt/vtgate/legacy_scatter_conn_test.go b/go/vt/vtgate/legacy_scatter_conn_test.go index 9b3679ac3ae..aaac0c20e31 100644 --- a/go/vt/vtgate/legacy_scatter_conn_test.go +++ b/go/vt/vtgate/legacy_scatter_conn_test.go @@ -17,28 +17,26 @@ limitations under the License. package vtgate import ( + "context" "fmt" "reflect" "strings" "testing" - "vitess.io/vitess/go/test/utils" - "github.com/stretchr/testify/assert" - - "context" - "github.com/stretchr/testify/require" "vitess.io/vitess/go/sqltypes" + "vitess.io/vitess/go/test/utils" "vitess.io/vitess/go/vt/discovery" "vitess.io/vitess/go/vt/key" + "vitess.io/vitess/go/vt/srvtopo" + "vitess.io/vitess/go/vt/vterrors" + querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" vtgatepb "vitess.io/vitess/go/vt/proto/vtgate" vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" - "vitess.io/vitess/go/vt/srvtopo" - "vitess.io/vitess/go/vt/vterrors" ) // This file uses the sandbox_test framework. @@ -391,15 +389,17 @@ func TestMultiExecs(t *testing.T) { rss := []*srvtopo.ResolvedShard{ { Target: &querypb.Target{ - Keyspace: "TestMultiExecs", - Shard: "0", + Keyspace: "TestMultiExecs", + Shard: "0", + TabletType: topodatapb.TabletType_REPLICA, }, Gateway: sbc0, }, { Target: &querypb.Target{ - Keyspace: "TestMultiExecs", - Shard: "1", + Keyspace: "TestMultiExecs", + Shard: "1", + TabletType: topodatapb.TabletType_REPLICA, }, Gateway: sbc1, }, @@ -419,7 +419,8 @@ func TestMultiExecs(t *testing.T) { }, } - _, _ = sc.ExecuteMultiShard(ctx, rss, queries, NewSafeSession(nil), false, false) + _, err := sc.ExecuteMultiShard(ctx, rss, queries, NewSafeSession(nil), false, false) + require.NoError(t, vterrors.Aggregate(err)) if len(sbc0.Queries) == 0 || len(sbc1.Queries) == 0 { t.Fatalf("didn't get expected query") } diff --git a/go/vt/vtgate/scatter_conn.go b/go/vt/vtgate/scatter_conn.go index e8d1da842e5..beea97c3d84 100644 --- a/go/vt/vtgate/scatter_conn.go +++ b/go/vt/vtgate/scatter_conn.go @@ -221,23 +221,7 @@ func (stc *ScatterConn) ExecuteMultiShard( qs, err = getQueryService(rs, info) if err != nil { - // an error here could mean that the tablet we were targeting earlier has changed type. - // if we have a transaction, we'll have to fail, but if we only had a reserved connection, - // we can create a new reserved connection to a new tablet that is on the right shard - // and has the right type - switch info.actionNeeded { - case nothing: - info.actionNeeded = reserve - case begin: - info.actionNeeded = reserveBegin - default: - return nil, err - } - retry := checkAndResetShardSession(info, err, session) - if retry != newQS { - return nil, err - } - qs = rs.Gateway + return nil, err } retryRequest := func(exec func()) { diff --git a/go/vt/vtgate/scatter_conn_test.go b/go/vt/vtgate/scatter_conn_test.go index a0797f89f23..2e820ed2a09 100644 --- a/go/vt/vtgate/scatter_conn_test.go +++ b/go/vt/vtgate/scatter_conn_test.go @@ -351,12 +351,15 @@ func TestReservedConnFail(t *testing.T) { }) sbc0Th := ths[0] sbc0Th.Serving = false + sbc0.NotServing = true sbc0Rep := hc.AddTestTablet("aa", "0", 2, keyspace, "0", topodatapb.TabletType_REPLICA, true, 1, nil) sbc0.Queries = nil + sbc0.ExecCount.Set(0) _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) - assert.Equal(t, 0, len(sbc0.Queries), "no attempt should be made as the tablet is not serving") - assert.Equal(t, 1, len(sbc0Rep.Queries), "first attempt should pass as it is healthy") + assert.EqualValues(t, 1, sbc0.ExecCount.Get(), "first attempt should be made on original tablet") + assert.EqualValues(t, 0, len(sbc0.Queries), "no query should be executed on it") + assert.Equal(t, 1, len(sbc0Rep.Queries), "this attempt on new healthy tablet should pass") require.Equal(t, 1, len(session.ShardSessions)) assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") assert.NotEqual(t, oldAlias, session.Session.ShardSessions[0].TabletAlias, "tablet alias should have changed as this is a different tablet") @@ -376,12 +379,17 @@ func TestReservedConnFail(t *testing.T) { Shard: tablet0Rep.GetShard(), TabletType: topodatapb.TabletType_SPARE, } + sbc0Rep.Tablet().Type = topodatapb.TabletType_SPARE sbc0Th.Serving = true + sbc0.NotServing = false + sbc0.ExecCount.Set(0) sbc0Rep.Queries = nil + sbc0Rep.ExecCount.Set(0) _ = executeOnShardsReturnsErr(t, res, keyspace, sc, session, destinations) - assert.Equal(t, 1, len(sbc0.Queries), "first attempt should pass as it is healthy and matches the target") - assert.Equal(t, 0, len(sbc0Rep.Queries), " no attempt should be made as the tablet target is changed") + assert.EqualValues(t, 1, sbc0Rep.ExecCount.Get(), "first attempt should be made on the changed tablet type") + assert.EqualValues(t, 0, len(sbc0Rep.Queries), "no query should be executed on it") + assert.Equal(t, 1, len(sbc0.Queries), "this attempt should pass as it is on new healthy tablet and matches the target") require.Equal(t, 1, len(session.ShardSessions)) assert.NotEqual(t, oldRId, session.Session.ShardSessions[0].ReservedId, "should have recreated a reserved connection since the last connection was lost") assert.NotEqual(t, oldAlias, session.Session.ShardSessions[0].TabletAlias, "tablet alias should have changed as this is a different tablet") diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 035ca529fcd..313d6d0f955 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -22,6 +22,8 @@ import ( "fmt" "sync" + "vitess.io/vitess/go/vt/sqlparser" + "context" "vitess.io/vitess/go/sqltypes" @@ -108,6 +110,8 @@ type SandboxConn struct { // this error will only happen once EphemeralShardErr error + + NotServing bool } var _ queryservice.QueryService = (*SandboxConn)(nil) // compile-time interface check @@ -147,6 +151,12 @@ func (sbc *SandboxConn) Execute(ctx context.Context, target *querypb.Target, que sbc.execMu.Lock() defer sbc.execMu.Unlock() sbc.ExecCount.Add(1) + if sbc.NotServing { + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, vterrors.NotServing) + } + if sbc.tablet.Type != target.TabletType { + return nil, vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, "%s: %v, want: %v", vterrors.WrongTablet, target.TabletType, sbc.tablet.Type) + } bv := make(map[string]*querypb.BindVariable) for k, v := range bindVars { bv[k] = v @@ -159,7 +169,8 @@ func (sbc *SandboxConn) Execute(ctx context.Context, target *querypb.Target, que if err := sbc.getError(); err != nil { return nil, err } - return sbc.getNextResult(), nil + parse, _ := sqlparser.Parse(query) + return sbc.getNextResult(parse), nil } // ExecuteBatch is part of the QueryService interface. @@ -174,8 +185,9 @@ func (sbc *SandboxConn) ExecuteBatch(ctx context.Context, target *querypb.Target sbc.BatchQueries = append(sbc.BatchQueries, queries) sbc.Options = append(sbc.Options, options) result := make([]sqltypes.Result, 0, len(queries)) - for range queries { - result = append(result, *(sbc.getNextResult())) + for _, query := range queries { + parse, _ := sqlparser.Parse(query.Sql) + result = append(result, *(sbc.getNextResult(parse))) } return result, nil } @@ -198,14 +210,15 @@ func (sbc *SandboxConn) StreamExecute(ctx context.Context, target *querypb.Targe sbc.sExecMu.Unlock() return err } + ast, _ := sqlparser.Parse(query) if sbc.results == nil { - nextRs := sbc.getNextResult() + nextRs := sbc.getNextResult(ast) sbc.sExecMu.Unlock() return callback(nextRs) } for len(sbc.results) > 0 { - nextRs := sbc.getNextResult() + nextRs := sbc.getNextResult(ast) sbc.sExecMu.Unlock() err := callback(nextRs) if err != nil { @@ -378,7 +391,7 @@ func (sbc *SandboxConn) MessageStream(ctx context.Context, target *querypb.Targe if err := sbc.getError(); err != nil { return err } - r := sbc.getNextResult() + r := sbc.getNextResult(nil) if r == nil { return nil } @@ -505,13 +518,55 @@ func (sbc *SandboxConn) Tablet() *topodatapb.Tablet { return sbc.tablet } -func (sbc *SandboxConn) getNextResult() *sqltypes.Result { +func (sbc *SandboxConn) getNextResult(stmt sqlparser.Statement) *sqltypes.Result { if len(sbc.results) != 0 { r := sbc.results[0] sbc.results = sbc.results[1:] return r } - return SingleRowResult + if stmt == nil { + // if we didn't get a valid query, we'll assume we need a SELECT + return getSingleRowResult() + } + switch stmt.(type) { + case *sqlparser.Select, + *sqlparser.Union, + *sqlparser.Show, + *sqlparser.Explain, + *sqlparser.OtherRead: + return getSingleRowResult() + case *sqlparser.Set, + sqlparser.DDLStatement, + *sqlparser.AlterVschema, + *sqlparser.Use, + *sqlparser.OtherAdmin, + *sqlparser.SetTransaction, + *sqlparser.Savepoint, + *sqlparser.SRollback, + *sqlparser.Release: + return &sqltypes.Result{} + } + + // for everything else we fake a single row being affected + return &sqltypes.Result{RowsAffected: 1} +} + +// getSingleRowResult is used to get a SingleRowResult but it creates separate fields because some tests change the fields +// If these fields are not created separately then the constants value also changes which leads to some other tests failing later +func getSingleRowResult() *sqltypes.Result { + singleRowResult := &sqltypes.Result{ + InsertID: SingleRowResult.InsertID, + Rows: SingleRowResult.Rows, + } + + for _, field := range SingleRowResult.Fields { + singleRowResult.Fields = append(singleRowResult.Fields, &querypb.Field{ + Name: field.Name, + Type: field.Type, + }) + } + + return singleRowResult } //StringQueries returns the queries executed as a slice of strings From c974aaa5a00401146e469211968caa3eee2668cf Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 16 Mar 2021 17:58:42 -0700 Subject: [PATCH 44/49] restore: check disable_active_reparents properly before waiting for position update Signed-off-by: deepthi --- go/vt/vttablet/tabletmanager/restore.go | 2 +- go/vt/wrangler/testlib/backup_test.go | 204 ++++++++++++++++++++++++ 2 files changed, 205 insertions(+), 1 deletion(-) diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index 790b41fed65..d85aa45f5cc 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -497,7 +497,7 @@ func (tm *TabletManager) startReplication(ctx context.Context, pos mysql.Positio // If active reparents are disabled, we don't restart replication. So it makes no sense to wait for an update on the replica. // Return immediately. - if !*mysqlctl.DisableActiveReparents { + if *mysqlctl.DisableActiveReparents { return nil } // wait for reliable seconds behind master diff --git a/go/vt/wrangler/testlib/backup_test.go b/go/vt/wrangler/testlib/backup_test.go index c33437a4c1d..8399102b959 100644 --- a/go/vt/wrangler/testlib/backup_test.go +++ b/go/vt/wrangler/testlib/backup_test.go @@ -245,6 +245,210 @@ func TestBackupRestore(t *testing.T) { assert.True(t, master.FakeMysqlDaemon.Running) } +// TestBackupRestoreLagged tests the changes made in https://github.com/vitessio/vitess/pull/5000 +// While doing a backup or a restore, we wait for a change of the replica's position before completing the action +// This is because otherwise SecondsBehindMaster is not accurate and the tablet may go into SERVING when it should not +func TestBackupRestoreLagged(t *testing.T) { + delay := discovery.GetTabletPickerRetryDelay() + defer func() { + discovery.SetTabletPickerRetryDelay(delay) + }() + discovery.SetTabletPickerRetryDelay(5 * time.Millisecond) + + // Initialize our environment + ctx := context.Background() + db := fakesqldb.New(t) + defer db.Close() + ts := memorytopo.NewServer("cell1", "cell2") + wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient()) + vp := NewVtctlPipe(t, ts) + defer vp.Close() + + // Set up mock query results. + db.AddQuery("CREATE DATABASE IF NOT EXISTS _vt", &sqltypes.Result{}) + db.AddQuery("BEGIN", &sqltypes.Result{}) + db.AddQuery("COMMIT", &sqltypes.Result{}) + db.AddQueryPattern(`SET @@session\.sql_log_bin = .*`, &sqltypes.Result{}) + db.AddQueryPattern(`CREATE TABLE IF NOT EXISTS _vt\.shard_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`CREATE TABLE IF NOT EXISTS _vt\.local_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`ALTER TABLE _vt\.local_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`ALTER TABLE _vt\.shard_metadata .*`, &sqltypes.Result{}) + db.AddQueryPattern(`UPDATE _vt\.local_metadata SET db_name=.*`, &sqltypes.Result{}) + db.AddQueryPattern(`UPDATE _vt\.shard_metadata SET db_name=.*`, &sqltypes.Result{}) + db.AddQueryPattern(`INSERT INTO _vt\.local_metadata .*`, &sqltypes.Result{}) + + // Initialize our temp dirs + root, err := ioutil.TempDir("", "backuptest") + require.NoError(t, err) + defer os.RemoveAll(root) + + // Initialize BackupStorage + fbsRoot := path.Join(root, "fbs") + *filebackupstorage.FileBackupStorageRoot = fbsRoot + *backupstorage.BackupStorageImplementation = "file" + + // Initialize the fake mysql root directories + sourceInnodbDataDir := path.Join(root, "source_innodb_data") + sourceInnodbLogDir := path.Join(root, "source_innodb_log") + sourceDataDir := path.Join(root, "source_data") + sourceDataDbDir := path.Join(sourceDataDir, "vt_db") + for _, s := range []string{sourceInnodbDataDir, sourceInnodbLogDir, sourceDataDbDir} { + require.NoError(t, os.MkdirAll(s, os.ModePerm)) + } + require.NoError(t, ioutil.WriteFile(path.Join(sourceInnodbDataDir, "innodb_data_1"), []byte("innodb data 1 contents"), os.ModePerm)) + require.NoError(t, ioutil.WriteFile(path.Join(sourceInnodbLogDir, "innodb_log_1"), []byte("innodb log 1 contents"), os.ModePerm)) + require.NoError(t, ioutil.WriteFile(path.Join(sourceDataDbDir, "db.opt"), []byte("db opt file"), os.ModePerm)) + + // create a master tablet, set its master position + master := NewFakeTablet(t, wr, "cell1", 0, topodatapb.TabletType_MASTER, db) + master.FakeMysqlDaemon.ReadOnly = false + master.FakeMysqlDaemon.Replicating = false + master.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + + // start master so that replica can fetch master position from it + master.StartActionLoop(t, wr) + defer master.StopActionLoop(t) + + // create a single tablet, set it up so we can do backups + // set its position same as that of master so that backup doesn't wait for catchup + sourceTablet := NewFakeTablet(t, wr, "cell1", 1, topodatapb.TabletType_REPLICA, db) + sourceTablet.FakeMysqlDaemon.ReadOnly = true + sourceTablet.FakeMysqlDaemon.Replicating = true + sourceTablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 456, + }, + }, + } + sourceTablet.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP SLAVE", + "START SLAVE", + } + sourceTablet.StartActionLoop(t, wr) + defer sourceTablet.StopActionLoop(t) + + sourceTablet.TM.Cnf = &mysqlctl.Mycnf{ + DataDir: sourceDataDir, + InnodbDataHomeDir: sourceInnodbDataDir, + InnodbLogGroupHomeDir: sourceInnodbLogDir, + } + + timer := time.NewTicker(1 * time.Second) + go func(tablet *FakeTablet) { + <-timer.C + tablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + }(sourceTablet) + + errCh := make(chan error, 1) + go func(ctx context.Context, tablet *FakeTablet) { + errCh <- vp.Run([]string{"Backup", topoproto.TabletAliasString(tablet.Tablet.Alias)}) + }(ctx, sourceTablet) + + timer2 := time.NewTicker(5 * time.Second) + select { + case err := <-errCh: + require.Nil(t, err) + // verify the full status + // verify the full status + require.NoError(t, sourceTablet.FakeMysqlDaemon.CheckSuperQueryList()) + assert.True(t, sourceTablet.FakeMysqlDaemon.Replicating) + assert.True(t, sourceTablet.FakeMysqlDaemon.Running) + assert.Equal(t, master.FakeMysqlDaemon.CurrentMasterPosition, sourceTablet.FakeMysqlDaemon.CurrentMasterPosition) + case <-timer2.C: + require.FailNow(t, "Backup timed out") + } + + // create a destination tablet, set it up so we can do restores + destTablet := NewFakeTablet(t, wr, "cell1", 2, topodatapb.TabletType_REPLICA, db) + destTablet.FakeMysqlDaemon.ReadOnly = true + destTablet.FakeMysqlDaemon.Replicating = true + destTablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 456, + }, + }, + } + destTablet.FakeMysqlDaemon.ExpectedExecuteSuperQueryList = []string{ + "STOP SLAVE", + "RESET SLAVE ALL", + "FAKE SET SLAVE POSITION", + "FAKE SET MASTER", + "START SLAVE", + } + destTablet.FakeMysqlDaemon.FetchSuperQueryMap = map[string]*sqltypes.Result{ + "SHOW DATABASES": {}, + } + destTablet.FakeMysqlDaemon.SetReplicationPositionPos = destTablet.FakeMysqlDaemon.CurrentMasterPosition + destTablet.FakeMysqlDaemon.SetMasterInput = topoproto.MysqlAddr(master.Tablet) + + destTablet.StartActionLoop(t, wr) + defer destTablet.StopActionLoop(t) + + destTablet.TM.Cnf = &mysqlctl.Mycnf{ + DataDir: sourceDataDir, + InnodbDataHomeDir: sourceInnodbDataDir, + InnodbLogGroupHomeDir: sourceInnodbLogDir, + BinLogPath: path.Join(root, "bin-logs/filename_prefix"), + RelayLogPath: path.Join(root, "relay-logs/filename_prefix"), + RelayLogIndexPath: path.Join(root, "relay-log.index"), + RelayLogInfoPath: path.Join(root, "relay-log.info"), + } + + timer = time.NewTicker(1 * time.Second) + go func(tablet *FakeTablet) { + <-timer.C + tablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + } + }(destTablet) + + errCh = make(chan error, 1) + go func(ctx context.Context, tablet *FakeTablet) { + errCh <- tablet.TM.RestoreData(ctx, logutil.NewConsoleLogger(), 0 /* waitForBackupInterval */, false /* deleteBeforeRestore */) + }(ctx, destTablet) + + timer2 = time.NewTicker(5 * time.Second) + select { + case err := <-errCh: + require.Nil(t, err) + // verify the full status + require.NoError(t, destTablet.FakeMysqlDaemon.CheckSuperQueryList(), "destTablet.FakeMysqlDaemon.CheckSuperQueryList failed") + assert.True(t, destTablet.FakeMysqlDaemon.Replicating) + assert.True(t, destTablet.FakeMysqlDaemon.Running) + assert.Equal(t, master.FakeMysqlDaemon.CurrentMasterPosition, destTablet.FakeMysqlDaemon.CurrentMasterPosition) + case <-timer2.C: + require.FailNow(t, "Restore timed out") + } +} + func TestRestoreUnreachableMaster(t *testing.T) { delay := discovery.GetTabletPickerRetryDelay() defer func() { From 150f28139ba941b22f0bcb8b96a705a05c223130 Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 16 Mar 2021 19:06:42 -0700 Subject: [PATCH 45/49] restore: call orc.EndMaintenance only if there is no error Signed-off-by: deepthi --- go/vt/vttablet/tabletmanager/restore.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/go/vt/vttablet/tabletmanager/restore.go b/go/vt/vttablet/tabletmanager/restore.go index d85aa45f5cc..818c8d162c1 100644 --- a/go/vt/vttablet/tabletmanager/restore.go +++ b/go/vt/vttablet/tabletmanager/restore.go @@ -89,6 +89,9 @@ func (tm *TabletManager) RestoreData(ctx context.Context, logger logutil.Logger, } }() err := tm.restoreDataLocked(ctx, logger, waitForBackupInterval, deleteBeforeRestore) + if err != nil { + return err + } // Tell Orchestrator we're no longer stopped on purpose. // Do this in the background, as it's best-effort. go func() { @@ -99,7 +102,7 @@ func (tm *TabletManager) RestoreData(ctx context.Context, logger logutil.Logger, log.Warningf("Orchestrator EndMaintenance failed: %v", err) } }() - return err + return nil } func (tm *TabletManager) restoreDataLocked(ctx context.Context, logger logutil.Logger, waitForBackupInterval time.Duration, deleteBeforeRestore bool) error { From 8fd2b640f52b2c9b11f1e90f27997db7f7c676a0 Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 16 Mar 2021 19:07:04 -0700 Subject: [PATCH 46/49] backup: call orc.EndMaintenance only if there is no error Signed-off-by: deepthi --- go/vt/vttablet/tabletmanager/rpc_backup.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/go/vt/vttablet/tabletmanager/rpc_backup.go b/go/vt/vttablet/tabletmanager/rpc_backup.go index 683d69b2064..caaf7107790 100644 --- a/go/vt/vttablet/tabletmanager/rpc_backup.go +++ b/go/vt/vttablet/tabletmanager/rpc_backup.go @@ -133,17 +133,18 @@ func (tm *TabletManager) Backup(ctx context.Context, concurrency int, logger log l.Errorf("mysql backup command returned error: %v", returnErr) } returnErr = err + } else { + // Tell Orchestrator we're no longer stopped on purpose. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.EndMaintenance(tm.Tablet()); err != nil { + logger.Warningf("Orchestrator EndMaintenance failed: %v", err) + } + }() } - // Tell Orchestrator we're no longer stopped on purpose. - // Do this in the background, as it's best-effort. - go func() { - if tm.orc == nil { - return - } - if err := tm.orc.EndMaintenance(tm.Tablet()); err != nil { - logger.Warningf("Orchestrator EndMaintenance failed: %v", err) - } - }() } return returnErr From 5db56670e0b1cb9d1cd938d8addd6bde89f598eb Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 16 Mar 2021 19:07:38 -0700 Subject: [PATCH 47/49] replication: call orc.EndMaintenance in UndoDemoteMaster Signed-off-by: deepthi --- go/vt/vttablet/tabletmanager/rpc_replication.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/go/vt/vttablet/tabletmanager/rpc_replication.go b/go/vt/vttablet/tabletmanager/rpc_replication.go index 348832974bc..eeb08050009 100644 --- a/go/vt/vttablet/tabletmanager/rpc_replication.go +++ b/go/vt/vttablet/tabletmanager/rpc_replication.go @@ -462,7 +462,16 @@ func (tm *TabletManager) UndoDemoteMaster(ctx context.Context) error { if err := tm.QueryServiceControl.SetServingType(tablet.Type, logutil.ProtoToTime(tablet.MasterTermStartTime), true, ""); err != nil { return vterrors.Wrap(err, "SetServingType(serving=true) failed") } - + // Tell Orchestrator we're no longer stopped on purpose. + // Do this in the background, as it's best-effort. + go func() { + if tm.orc == nil { + return + } + if err := tm.orc.EndMaintenance(tm.Tablet()); err != nil { + log.Warningf("Orchestrator EndMaintenance failed: %v", err) + } + }() return nil } From 320376d54b249912842fb9f209b8215770210017 Mon Sep 17 00:00:00 2001 From: deepthi Date: Tue, 16 Mar 2021 19:54:00 -0700 Subject: [PATCH 48/49] tests: add mutex to FakeMysqlDaemon Signed-off-by: deepthi --- .../fakemysqldaemon/fakemysqldaemon.go | 11 ++++ go/vt/wrangler/testlib/backup_test.go | 52 +++++++++---------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go index 58502a90d62..9d2fa9ef6da 100644 --- a/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go +++ b/go/vt/mysqlctl/fakemysqldaemon/fakemysqldaemon.go @@ -20,6 +20,7 @@ import ( "fmt" "reflect" "strings" + "sync" "time" "context" @@ -39,6 +40,7 @@ import ( // FakeMysqlDaemon implements MysqlDaemon and allows the user to fake // everything. type FakeMysqlDaemon struct { + mu sync.Mutex // db is the fake SQL DB we may use for some queries. db *fakesqldb.DB @@ -248,11 +250,20 @@ func (fmd *FakeMysqlDaemon) GetMysqlPort() (int32, error) { return fmd.MysqlPort.Get(), nil } +// CurrentMasterPositionLocked is thread-safe +func (fmd *FakeMysqlDaemon) CurrentMasterPositionLocked(pos mysql.Position) { + fmd.mu.Lock() + defer fmd.mu.Unlock() + fmd.CurrentMasterPosition = pos +} + // ReplicationStatus is part of the MysqlDaemon interface func (fmd *FakeMysqlDaemon) ReplicationStatus() (mysql.ReplicationStatus, error) { if fmd.ReplicationStatusError != nil { return mysql.ReplicationStatus{}, fmd.ReplicationStatusError } + fmd.mu.Lock() + defer fmd.mu.Unlock() return mysql.ReplicationStatus{ Position: fmd.CurrentMasterPosition, FilePosition: fmd.CurrentMasterFilePosition, diff --git a/go/vt/wrangler/testlib/backup_test.go b/go/vt/wrangler/testlib/backup_test.go index 8399102b959..249bc1afa24 100644 --- a/go/vt/wrangler/testlib/backup_test.go +++ b/go/vt/wrangler/testlib/backup_test.go @@ -344,25 +344,23 @@ func TestBackupRestoreLagged(t *testing.T) { InnodbLogGroupHomeDir: sourceInnodbLogDir, } - timer := time.NewTicker(1 * time.Second) - go func(tablet *FakeTablet) { - <-timer.C - tablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ - GTIDSet: mysql.MariadbGTIDSet{ - 2: mysql.MariadbGTID{ - Domain: 2, - Server: 123, - Sequence: 457, - }, - }, - } - }(sourceTablet) - errCh := make(chan error, 1) go func(ctx context.Context, tablet *FakeTablet) { errCh <- vp.Run([]string{"Backup", topoproto.TabletAliasString(tablet.Tablet.Alias)}) }(ctx, sourceTablet) + timer := time.NewTicker(1 * time.Second) + <-timer.C + sourceTablet.FakeMysqlDaemon.CurrentMasterPositionLocked(mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + }) + timer2 := time.NewTicker(5 * time.Second) select { case err := <-errCh: @@ -416,25 +414,23 @@ func TestBackupRestoreLagged(t *testing.T) { RelayLogInfoPath: path.Join(root, "relay-log.info"), } - timer = time.NewTicker(1 * time.Second) - go func(tablet *FakeTablet) { - <-timer.C - tablet.FakeMysqlDaemon.CurrentMasterPosition = mysql.Position{ - GTIDSet: mysql.MariadbGTIDSet{ - 2: mysql.MariadbGTID{ - Domain: 2, - Server: 123, - Sequence: 457, - }, - }, - } - }(destTablet) - errCh = make(chan error, 1) go func(ctx context.Context, tablet *FakeTablet) { errCh <- tablet.TM.RestoreData(ctx, logutil.NewConsoleLogger(), 0 /* waitForBackupInterval */, false /* deleteBeforeRestore */) }(ctx, destTablet) + timer = time.NewTicker(1 * time.Second) + <-timer.C + destTablet.FakeMysqlDaemon.CurrentMasterPositionLocked(mysql.Position{ + GTIDSet: mysql.MariadbGTIDSet{ + 2: mysql.MariadbGTID{ + Domain: 2, + Server: 123, + Sequence: 457, + }, + }, + }) + timer2 = time.NewTicker(5 * time.Second) select { case err := <-errCh: From 345b61baeb8a3b6bbea7ff2b19a293cca420914a Mon Sep 17 00:00:00 2001 From: deepthi Date: Thu, 13 May 2021 14:52:36 -0700 Subject: [PATCH 49/49] fix unit tests Signed-off-by: deepthi --- go/vt/vttablet/sandboxconn/sandboxconn.go | 63 +++-------------------- 1 file changed, 8 insertions(+), 55 deletions(-) diff --git a/go/vt/vttablet/sandboxconn/sandboxconn.go b/go/vt/vttablet/sandboxconn/sandboxconn.go index 313d6d0f955..912fd19f5b0 100644 --- a/go/vt/vttablet/sandboxconn/sandboxconn.go +++ b/go/vt/vttablet/sandboxconn/sandboxconn.go @@ -22,8 +22,6 @@ import ( "fmt" "sync" - "vitess.io/vitess/go/vt/sqlparser" - "context" "vitess.io/vitess/go/sqltypes" @@ -169,8 +167,7 @@ func (sbc *SandboxConn) Execute(ctx context.Context, target *querypb.Target, que if err := sbc.getError(); err != nil { return nil, err } - parse, _ := sqlparser.Parse(query) - return sbc.getNextResult(parse), nil + return sbc.getNextResult(), nil } // ExecuteBatch is part of the QueryService interface. @@ -185,9 +182,8 @@ func (sbc *SandboxConn) ExecuteBatch(ctx context.Context, target *querypb.Target sbc.BatchQueries = append(sbc.BatchQueries, queries) sbc.Options = append(sbc.Options, options) result := make([]sqltypes.Result, 0, len(queries)) - for _, query := range queries { - parse, _ := sqlparser.Parse(query.Sql) - result = append(result, *(sbc.getNextResult(parse))) + for range queries { + result = append(result, *(sbc.getNextResult())) } return result, nil } @@ -210,15 +206,14 @@ func (sbc *SandboxConn) StreamExecute(ctx context.Context, target *querypb.Targe sbc.sExecMu.Unlock() return err } - ast, _ := sqlparser.Parse(query) if sbc.results == nil { - nextRs := sbc.getNextResult(ast) + nextRs := sbc.getNextResult() sbc.sExecMu.Unlock() return callback(nextRs) } for len(sbc.results) > 0 { - nextRs := sbc.getNextResult(ast) + nextRs := sbc.getNextResult() sbc.sExecMu.Unlock() err := callback(nextRs) if err != nil { @@ -391,7 +386,7 @@ func (sbc *SandboxConn) MessageStream(ctx context.Context, target *querypb.Targe if err := sbc.getError(); err != nil { return err } - r := sbc.getNextResult(nil) + r := sbc.getNextResult() if r == nil { return nil } @@ -518,55 +513,13 @@ func (sbc *SandboxConn) Tablet() *topodatapb.Tablet { return sbc.tablet } -func (sbc *SandboxConn) getNextResult(stmt sqlparser.Statement) *sqltypes.Result { +func (sbc *SandboxConn) getNextResult() *sqltypes.Result { if len(sbc.results) != 0 { r := sbc.results[0] sbc.results = sbc.results[1:] return r } - if stmt == nil { - // if we didn't get a valid query, we'll assume we need a SELECT - return getSingleRowResult() - } - switch stmt.(type) { - case *sqlparser.Select, - *sqlparser.Union, - *sqlparser.Show, - *sqlparser.Explain, - *sqlparser.OtherRead: - return getSingleRowResult() - case *sqlparser.Set, - sqlparser.DDLStatement, - *sqlparser.AlterVschema, - *sqlparser.Use, - *sqlparser.OtherAdmin, - *sqlparser.SetTransaction, - *sqlparser.Savepoint, - *sqlparser.SRollback, - *sqlparser.Release: - return &sqltypes.Result{} - } - - // for everything else we fake a single row being affected - return &sqltypes.Result{RowsAffected: 1} -} - -// getSingleRowResult is used to get a SingleRowResult but it creates separate fields because some tests change the fields -// If these fields are not created separately then the constants value also changes which leads to some other tests failing later -func getSingleRowResult() *sqltypes.Result { - singleRowResult := &sqltypes.Result{ - InsertID: SingleRowResult.InsertID, - Rows: SingleRowResult.Rows, - } - - for _, field := range SingleRowResult.Fields { - singleRowResult.Fields = append(singleRowResult.Fields, &querypb.Field{ - Name: field.Name, - Type: field.Type, - }) - } - - return singleRowResult + return SingleRowResult } //StringQueries returns the queries executed as a slice of strings